Constructors work almost exactly the same way in C++ and Java. If you do not define a constructor for a class then it is allocated a default constructor. If we do define a constructor then we must use it. The only significant difference is that there is no copy constructor in Java as all objects of a class (i.e. non-primitive types) are passed by reference.
There are no destructors in Java, even thought there is a new
keyword, there is no corresponding
delete
keyword, as Java takes care of all of the memory management. Java has a special
finalize()
method that you can add to any class. The strange thing about this method is that you can
use it for tidying up (printing a paper record for Account
etc.), but you do not know when it will
be called. In C++ this was easier, as the destructor is called when the object goes out of scope, but in Java the
finalize()
method will be called when the garbage collector destroys the object. We do not know when
this will be called! As discussed previously, we can request that the garbage collector should run, but we do not know when
it will run! You can help the garbage collector slightly by setting all your references to null
when
you no longer need them, e.g. a = null;
- will send a hint to the garbage collector that the
object is no longer being used.
Like C++, in Java we have public
, private
and protected
access
specifiers, but we also have another access specifier "package". This is the default access specifier and means that
all states and methods are accessible to all classes within the same package. There is no package access specifier keyword,
it is simply the default if public
, private
or protected
are not
used. Access specifiers in Java are:
public
- accessible everywhere, an interface method (same as C++)
private
- accessible only in the class where it was defined (same as C++)
protected
- accessible in the class where it is defined, the derived classes and in the
same package (almost the same as C++ with the exception of the package)
"package
" - default (there is no package
specifier keyword) and means
that it is accessible by any class in the same package. You can equate this to the C++ friendly condition by saying that all
of the classes in the same package (directory) are friendly.
In Java there is no direct equivalent to protected
in C++. In Java version 1.0 there was! it was
called "private protected
", but was deemed complex and unnecessary, and so was removed.
Inheritance in Java does not change the protection level of the members in the base class. You cannot specify
public
, private
or protected
inheritance in Java, as you can
in C++. Over-ridden methods in a derived class cannot reduce the access of the method in the base class. For
example, if a method is public in the base class and you over-ride it, your over-ridden method must also be
public. The compiler will enforce this rule.
In C++ methods are non-virtual by default, so to replace the behaviour (allow over-riding) of a method in the derived
class you have to explicitly use the virtual
keyword in the parent class. You are able to replace the behaviour
of a non-virtual method but this causes serious difficulties when the behaviour of the object depends on the static
rather than the dynamic type! In Java, methods are virtual by default and we always operate on the dynamic type of the
object. You cannot specify a method as non-virtual, but there is a final
keyword. Once you
use the final
keyword on a method you cannot replace it - so there are no issues with static and
dynamic types.
C++ allows multiple inheritance - Java does not! As discussed previously in the C++ section of the notes, multiple inheritance is complex for the programmer, in that they must make complex decisions about the way that the data of the base class is to be inherited. In Java, we do not have multiple inheritance but we do have the use of Interfaces. Interfaces are a special kind of abstract class that have no data or implemented code. Interfaces might not sound too useful, but they allow a form of multiple inheritance, without having the associated difficulties of dealing with data. This replacement behaviour works very well and does not impact on development, once you get used to the change.
There is no scope resolution operator in Java - such as Account::display();
as used
previously in C++. This is possible because you must define all methods and states within a class so there is no
global namespace as we had in C++. We have the super
and this
keywords which
allow us to access the parent (only through the direct parent) and the states of a class. Packages are used instead
of namespaces. When you use the super()
method call in the constructor to call the parent
constructor it must be the first line of the child constructor implementation.
In Java we have the facility to define a class inside of another class. We refer to this class as an inner class. The only issue worth mentioning with inner classes is that they have full access to the private data and methods of the class in which they are nested. Because of this, we do not need to pass state pointers to methods that need callback.
In C++ we had inline methods, generally short methods that the compiler in effect cuts-and-pastes
the method code into the final program, leading to greater efficiency as the assembly language program
counter is not jumping around in the final executable. There is of course a trade-off between speed of
execution and size of the executable. There are no inline methods in Java - well that's not entirely true. It is
up to the compiler to decide whether a method should or should not be inline. There is a keyword
in Java called final
which suggests to the compiler that the method should be inline,
but you have no guarantee that the compiler will agree!
© 2006 Dr. Derek Molloy (DCU).