Quick Java Tutorial (with C++ programmers in mind)
Yannis Smaragdakis



1. Preliminaries, Environment

Hello World Java program:
public class Test {
  public static void main(String [] args) {
    System.out.println("Hello, World!");
  }
}

Note there is no semicolon at the end (unlike in C++).
Important points:

The above is in a "package" (the Java notion for namespaces) called the "default package". It's nameless. You could put your class in a package, say, "mypack" by adding the line "package mypack;" at the beginning of the file. Packages are hierarchical and are typically the way to organize libraries or applications. They correspond to directories in the file system. If the above class was in a directory "myFirstExamples", which was itself under a directory "myJavaCode", we could add the class in a corresponding package "myJavaCode.myFirstExamples":

package myJavaCode.myFirstExamples;

public class Test {
  public static void main(String [] args) {
    System.out.println("Hello, World!");
  }
}

In this case, you can still compile the file from the directory it's in using "javac Test.java". But when you try to run it using "java Test" you will receive a message such as "Exception in thread "main" java.lang.NoClassDefFoundError: Test (wrong name: myJavaCode/myFirstExamples/Test)".

The class can be run if you go to the parent directory of "myJavaCode" and use "java myJavaCode.myFirstExamples". You can also add that parent directory to your Java CLASSPATH (an environment variable in your shell, or a variable in your IDE). But your class's name is now "myJavaCode.myFirstExamples.Test", not just "Test". This is how other code (outside this package) will refer to it.

The package mechanism is something you need to employ when you use functionality from the Java libraries. Look at the documentation of the standard library. (You should do this often, by the way!) Locate a class, say class Dialog. Notice the "java.awt" prefix before the name of the class. To use this class, you can either refer to it by its full name ("java.awt.Dialog"), or you can write "import java.awt.*;" at the top of your program (which will let you use any name from the java.awt package without qualifying it), or you can be explicit and say "import java.awt.Dialog;" (which will only let you use this class without qualification).

2. Obvious Differences

In Java everything is part of a class. There are no free-floating variables or functions. This doesn't make a big difference. We already saw how the "main" function is a static method of a class. A static member of a class, like in C++, is one that exists always, independently of objects. The only difference is that outside the class you will need to use names such as "Test.main" instead of just "main" for a static member function (and similarly for static fields). In fact, you already did this. You wrote "System.out.println...". This means "call method println on the static member called out inside class System".

Another obvious difference is that the "public" keyword (and similarly, private, and protected, as in C++, but with a slightly different meaning, as we'll see) is attached to every member of a class individually and not to a range of members.

Java has no preprocessor (no #define, #include, #ifdef). You can define constants as fields with the attribute "final", which is something like "const". You can refer to packages you "import" (somewhat analogously to #include, although very different). The rest of the functionality (macros, conditional compilation) is not supported inside the language.


3. Deep Differences

The biggest difference in Java is that the language has no pointers or references. Or you can look at it a different way: the language has no pointers to primitive types (ints, doubles, and the like) and only has pointers for objects--there is no other way to refer to an object, so the pointer is there but it's not even named.

In C++ you might write:
class A {
public:
  int i;
  A() {i=0;}
};
void foo1(A *pa) { pa->i = 1; }
void foo2(A a) { a.i = 2; }
void foo3(A &ra) { a.i = 3; }

A a;         // value of a.i is 0
foo1(&a);    // value of a.i becomes 1
foo2(a);     // value of a.i remains 1
foo3(a);     // value of a.i becomes 3

In Java there is only one way to pass an object to a function. You can think of it as always passing a pointer. In Java parlance, this is called a "reference" but it's not the same as a C++ reference.
class A {
  int i;
  A() {i=0;}
}
void foo(A pa) { pa.i = 1; }

A a = new A();       // value of a.i is 0

foo(a);              // value of a.i becomes 1

Notice another difference? We created an object but had to use "new A()". (Just like with pointers in C++.) That's the only way to create objects in Java and the only way to refer to them! There is no way to have local objects ("on the stack", so to speak), only local pointers to objects that are allocated via "new". We cannot have entire objects as members. E.g., in C++ we can write:
class B {
   A a;
};
in which case a B object contains an entire A object in it. If you write the same thing (sans the final semicolon) in Java, it means that the B object contains a reference (think "pointer") to an A object. Of course, if you declare a Java reference and don't set its value (by assigning it a "new" expression or an existing object reference) then it's not usable.

So, going back to primitive types (namely, int, byte, float, boolean, double, char, short, long). We said Java doesn't allow pointers to them. How do you do what you might want to do with a pointer to a primitive in C++? Well, what exactly would you want to do with a pointer to a primitive? A primitive is a value with a standard, small size. Why do you need a pointer to it? Either you need direct memory access (which Java does not allow: it is not a low-level language so it never lets you manipulate memory bytes) or you want to pass a primitive to a function and have it get changed. The only (partial) way to do this in Java is to wrap the primitive inside a class and pass a reference to the class instead of the primitive itself.

A final deep difference between Java and C++ is that Java has garbage collection. This means that you don't call "delete" on an object. Instead you make sure you set all references to it to null (which is the counterpart of C++'s NULL) or to some other object. When the last reference to an object disappears, the object it no longer reachable and some time later it will be automatically "deleted".


4. Semi-Deep Differences

A Java class can inherit from another by specifying that it "extends" it. A Java class can extend only a single other class. Java "interfaces" are like abstract classes in C++ with all their methods being pure virtual. That is, an interface is like a class, but it cannot have fields and all its methods are left to be defined in subclasses. A Java class can "implement" an interface, which is like "extends", but only for interfaces. A Java class can implement many interfaces. So, in Java we may have code like:
interface IntReadable {
  int read();
}

interface IntWriteable {
  void write(int i);
}

class C extends A implements IntReadable, IntWriteable {

  int read() { /* do something ... */ }
  void write(int i) { /* do something ... */ }

}

In C++, the same would be written as:
class IntReadable {
public:
  virtual int read() = 0;
};

class IntWriteable {
public:
  virtual void write(int i) = 0;
};

class C : public A, IntReadable, IntWriteable {

  int read() { /* do something ... */ }
  void write(int i) { /* do something ... */ }

};

Important points:

Another difference is in access protection modifiers (private, public, protected), which have slightly different meanings in Java. For a class's members:
- private means only accessible in class (almost like in C++, except Java has no "friend" concept)
- public means accessible by anyone (like in C++)
- protected means accessible by classes in the same package and by subclasses
- <nothing> means accessible by classes in the same package

Java supports arrays in the language, like C++, but there is no way to access array elements using pointers (since there are no pointers). Furthermore, an array is like a regular object. It always needs to be allocated using "new". An array supports the special field "length" that shows its size. A multidimensional array is just an array of arrays in Java: they can be of different lengths, they can be completely independent, they are not next to each other in memory (unlike C++). For instance:
int arr[][] = null; // there is no array yet, just a reference to an array!
arr = new int[100][];  // now there is an array of 100 int[] slots
for (int i = 0; i < 100; i++)
  arr[i] = new int[100-i];
// arr[i] is an array of length 100-i. Holds that many ints.
   


5. Further Things To Look Up

6. Other Differences

Java has:
But these are way beyond the scope of a quick tutorial. If you know what the above mean or need to use them, you are not going to be lost in a transition between Java and C++ -- you are too experienced for that.