Suppose you have this class definition: class Person { String firstName; String lastName; Person(String first, String last) { firstName = first; lastName = last; } } To create a new Person object, you would use a Java expression like this one: new Person("James", "Gosling") To compile this expression, two steps are necessary. First, the object itself must be created. Second, the constructor must be called. The code translates as new Person ; Create the uninitialized Person dup ; Duplicate the reference ldc "James" ; Push the first argument ldc "Gosling" ; Push the second argument ; Call the constructor: invokespecial Person/<init> (Ljava/lang/String;Ljava/lang/String;)V The first line creates the object but does not initialize it. The second instruction duplicates the reference to that object. When the invokespecial instruction is performed, it uses one of the copies of that reference, leaving the other on the stack. The entire sequence of code leaves exactly one item on the stack, a reference to the created and initialized Person object. This is the intended result of the new expression, which yields the newly created object. The constructor is always named <init>, no matter what the name of the class is. There can be more than one method named <init>. The compiler looks for one that matches the arguments given. This process is called overloading, and it's described in section 10.9.5. |