You don't need to declare something before you use it, so your files can read more naturally. The compiler will find it. Even if it is in a different file that the compiler sees.
Java has a garbage collector so there are no destructors. Memory management is handled by the system, not by each program.
Java catches all array subscript errors and similar. Java never has uninitialized data of any kind. Order of evaluation, etc. is completely defined and natural.
Java arrays know their own length. (a public read-only field named length.)
Java never has dangling references. You still can't derefernce null, however. If you try it will be caught. This is probably the most common run time error.
Java int, float,... are completely defined, so behave the same on all systems supporting Java. Int is 32 bits with modular arithmetic.
In fact the only thing in Java not specified is the effect of the interleaving of threads in a multithreaded program.
All casts are checked, either at compile time or at runtime. A narrowing cast is never applied automatically. You must specify it.
int x; ... long lo = x; // ok x = lo; // error x = (int) lo; // ok
Java interfaces define first class types. This gives most of the strength of both C++ templates and multiple inheritance. Interfaces are very important in Java.
Java has threads, so concurrent programs are possible with standard tools. They are simple enough to use so that you can teach simple concurrency in CS1.
Java has a library with lots of common data structures. Therefore, you can use them before you examine implementations in CS 241.
I/O takes explanation and getting used to. Java standard output is easy. Java standard input is harder. Other input/output is hard. (But its object model is very good.) See Java I/O Explained and Elementary Patterns: Strategy, Decorator, and Composite
Java exceptions must be caught and i/o statements throw exceptions.
Java classes do not separate the function headers from the bodies. A Java class is written all in one file. Interfaces can be used to achieve separation when necessary.
Class variable members can be initialized when declared, even with function calls. You don't need to do this in the constructor, though you may.
import is like #include, but stronger. It doesn't reread and reparse the text.
Java has no typedefs. They aren't needed as the typing system is simpler.
boolean (small b) is a real type, not confused with int. if( ) must take a boolean. This helps prevent lots of errors--especially those that confuse == with =.
All Java objects are heap based. You must call new to get an object.
Java arrays are always heap based and the  comes in a different place.
int  days = new int(12); // Java
int days ; // C++ but NOT Java
An array of objects of a certain kind has cells initialized to null, not to default objects of the class.
Foo  foos = new Foo ; foos.bar(); // null pointer exception. for(int i = 0; i < 10; ++i) // do this first foos[i] = new Foo(...);
Java has no goto, but it has multi level breaks instead. A multilevel break can leave any structured statement, not just loops and switch.
Java has no const keyword, but
public static final int = 12;
Java has no enum, use class
Java has no struct, use class
Java static inner classes are like c++ nested classes, but non-static inner classes have a more sophisticated semantics. The object of the inner class is associated with a specific outer class objects and has an implicit reference to it. The outer object and the inner object are "friendly" and can reference each others members.
Java has no "free" functions. Every function (and variable) is part of some class.
The main function can appear in any/every class. It has prototype
public static void main(String  args)
The args array of strings does not include the name of the program as its first (index zero) arg.
Java String objects are immutable. But you can easily generate new Strings from old. The catenation operator for strings is "+".
All Java objects know how to represent themselves as strings, since they implement toString(). Therefore you can write out a string representation of any object. You may need to override this method to have anything meaningful printed, of course.
Assignment of class type variables is reference assignment, not copying.
When you pass an object as a parameter, it is the reference variable that is "by value". The function can modify the object to which the parameter refers by sending it messages in the usual way. The object itself is NOT copied.
Java has ONLY pass by value and no functions can be passed. Instead pass an object that implements a known interface. This has the same power and stronger semantics since the object passed can carry static state information that a function cannot. (This will be explored in the short course.)
Java doesn't depend on copy constructors. Instead there is a clone method inherited from Object to do something similar.
Java has no default parameter values, but you can override functions to provide the same effect.
Java has no operator overloading yet. (I think this will come, but is not yet officially promised.)
Java does not yet have generics (templates). These ARE promised, but will be different and stronger than C++ templates. For now, interfaces provide most of the same functionality, but not the same efficiency.
Java has a reputation for being slower than C++. This is not inherent in the language, in fact. Java has more opportunities for optimization than C++ since it has stronger semantics that can be exploited by an optimizer. Java may someday be the standard by which we measure other languages (as Fortran --not C-- is now). Java can even now achieve excellent performance on compute bound programs, such as numerical analysis. On many programs, the garbage collector increases rather than decreases efficiency.
You can also consult:
which has an example written in both C++ and Java.
Last Updated: September 22, 2000