OCA Java SE 8 Method - Java Constructor








Creating Constructors

A constructor is a special method that matches the name of the class and has no return type.

Here's an example:

public class Dog { 
  public Dog() { 
    System.out.println("constructor"); 
  } 
} 

The name of the constructor, Dog, matches the name of the class, Dog, and there is no return type, not even void.

The following two methods are not valid constructors for the Dog class?

public dog() { }     // DOES NOT COMPILE 
public void Dog() { } 

The first one doesn't match the classname since Java is case sensitive. However, it is missing the return type.

The second method is a perfectly good method, but is not a constructor because it has a return type.

Constructors are used when creating a new object. A constructor is called when we write new followed by the name of the class we want to instantiate. For example:

new Dog() 

When Java sees the new keyword, it allocates memory for the new object. Java also looks for a constructor and calls it.

A constructor is used to initialize instance variables.

Here's a common way of writing a constructor:

1: public class Dog { 
2:   private String color; 
3:   public Dog(String color) { 
4:     this.color = color; 
5:  } 
6: } 

On line 4, we assign the parameter color to the instance variable color. The right side of the assignment refers to the parameter.

The left side of the assignment uses this to tell Java we want it to use the instance variable.

Example,
1: public class Dog { 
2:   private String color; 
3:   private int height; 
4:   private int length; 
5:   public Dog(int length, int theHeight) { 
6:      length = this.length;     // backwards
7:      height = theHeight;          // fine because a different name 
8:      this.color = "white";     // OK, but redundant 
9:   }  
10:  public static void main(String[] args) { 
11:    Dog b = new Dog(1, 2); 
12:    System.out.println(b.length + " " + b.height + " " + b.color); 
13:  } 
14:} 

Line 6 is incorrect. The instance variable length starts out with a 0 value.

Line 7 is more straightforward. The parameter theHeight and instance variable height have different names.

Finally, line 8 shows that it is allowed to use this even when there is no duplication of variable names.





Default Constructor

Every class in Java has a constructor whether you code one or not.

If you don't include any constructors for a class, Java will create one for you without any parameters.

This Java-created constructor is called the default constructor. Sometimes we call it the default no-arguments constructor for clarity. Here's an example:

public class Main { 
  public static void main(String[] args) { 
    Main rabbit = new Main();          // Calls default constructor 
  } 
} 

In the Main class, Java sees no constructor was coded and creates one. This default constructor is equivalent to typing this:

public Main() {} 

The default constructor has an empty parameter list and an empty body.

A default constructor is only supplied if there are no constructors present.

Which of these classes do you think has a default constructor?

class MyClass1 { 
} 
class MyClass2 { 
  public MyClass2() { } 
} 
class MyClass3 { 
  public MyClass3(boolean b) { } 
} 
class MyClass4 { 
  private MyClass4() { } 
} 

Only MyClass1 gets a default no-argument constructor. It doesn't have a constructor coded so Java generates a default no-argument constructor.

MyClass2 and MyClass3 both have public constructors already.

MyClass4 has a private constructor. Since these three classes have a constructor defined, the default no-argument constructor is not inserted for you.

Let's take a quick look at how to call these constructors:

1: public class Main { 
2:   public static void main(String[] args) { 
3:      MyClass1 r1 = new MyClass1(); 
4:      MyClass2 r2 = new MyClass2(); 
5:      MyClass3 r3 = new MyClass3(true); 
6:      MyClass4 r4 = new MyClass4(); // DOES NOT COMPILE 
7:   } 
} 

Line 3 calls the generated default no-argument constructor. Lines 4 and 5 call the user-provided constructors.

Line 6 does not compile. MyClass4 made the constructor private so that other classes could not call it.





Overloading Constructors

Constructors must have different parameters in order to be overloaded.

This example shows two constructors:

public class Dog { 
  private String color; 
  private int weight; 
  public Dog(int weight) {               // first constructor 
    this.weight = weight; 
    color = "brown"; 
  } 
  public Dog(int weight, String color) {     // second constructor 
   this.weight = weight; 
   this.color = color; 
  } 
} 

One of the constructors takes a single int parameter. The other takes an int and a String.

These parameter lists are different, so the constructors are successfully overloaded.

Java uses this keyword to refer to constructor.

When this is used as if it were a method, Java calls another constructor on the same instance of the class.

public Dog(int weight) { 
   this(weight, "brown"); 
} 

Now Java calls the constructor that takes two parameters. weight and color get set on this instance.

If you choose to call it, the this() call must be the first noncommented statement in the constructor.

3: public Dog(int weight) { 
4:   System.out.println("in constructor"); 
5:   // ready to call this 
6:   this(weight, "brown");     // DOES NOT COMPILE 
7: } 

Even though a print statement on line 4 doesn't change any variables, it is still a Java statement and is not allowed to be inserted before the call to this().

The comment on line 5 is fine. Comments don't run Java statements and are allowed anywhere.

Constructor Chaining

Overloaded constructors often call each other. We can have each constructor add one parameter until getting to the constructor that does all the work.

This approach is called constructor chaining.

In this example, all three constructors are chained.

public class Dog { 
   private int numTeeth; 
   private int numWhiskers; 
   private int weight; 
   public Dog(int weight) { 
     this(weight, 16);  // calls constructor with 2 parameters 
   } 

   public Dog(int weight, int numTeeth) { 
    this(weight, numTeeth, 6);  // calls constructor with 3 parameters 
   } 

   public Dog(int weight, int numTeeth, int numWhiskers) { 
     this.weight = weight; 
     this.numTeeth = numTeeth; 
     this.numWhiskers = numWhiskers; 
   } 
   public void print() { 
     System.out.println(weight + " " + numTeeth + " " + numWhiskers); 
   } 
   public static void main(String[] args) { 
     Dog mouse = new Dog(15); 
     mouse.print(); 
   } 
} 

The main() method calls the constructor with one parameter.

That constructor adds a second hard-coded value and calls the constructor with two parameters.

Final Fields

The final instance variables must be assigned a value exactly once.

We can assign the value in the line of the declaration and in an instance initializer. There is one more location this assignment can be done: in the constructor.

public class Main{ 
  private final int volume; 
  private final String name = "my name"; 
  public Main(int length, int width, int height) { 
   volume = length * width * height; 
  }
} 

The constructor is part of the initialization process, so it is allowed to assign final instance variables in it.

By the time the constructor completes, all final instance variables must have been set.

Order of Initialization

  • If there is a superclass, initialize it first.
  • Static variable declarations and static initializers in the order they appear in the Java source file.
  • Instance variable declarations and instance initializers in the order they appear in the Java source file.
  • The constructor initializes the values.

Example

Let's try the first example:

public class Main { 
  private String name = "aaa"; 
  { 
     System.out.println(name); 
  } 
  private static int COUNT = 0; 
  static { 
     System.out.println(COUNT); 
  } 
  static { 
     COUNT += 10; 
     System.out.println(COUNT); 
  } 
  public Main() { 
     System.out.println("constructor"); 
  } 
  public static void main(String[] args) { 
     Main init = new Main(); 
  } 
} 

If the class is referred to without a new call, only rules 1 and 2 apply.

The other two rules relate to instances and constructors. They have to wait until there is code to instantiate the object.

Example 2

What do you think happens here?

public class Main { 
   private String name = "aaa"; 
   { /* w  w w . j a va 2 s  .  c  o m*/
      System.out.println(name); 
   } 
   private static int COUNT = 0; 
   static { 
      System.out.println(COUNT); 
   } 
   { 
      COUNT++;  
      System.out.println(COUNT); 
   } 
   public Main() { 
      System.out.println("constructor"); 
   } 
   public static void main(String[] args) { 
      System.out.println("read to construct"); 
      new Main(); 
   } 
} 

The code above generates the following result.

Example 3

public class Main { 
  static { add(2); } 
  static void add(int num) { 
     System.out.print(num + " "); 
  } /*  w w w  . ja v a 2s.c  o m*/
  Main() { 
     add(5); 
  } 
  static { 
     add(4); 
  } 
  { 
     add(6); //also static
  } 
  static { 
     new Main(); 
  } 
  { 
     add(8); //also static
  } 
  public static void main(String[] args) { 
     new Main();
  } 
} 

The code above generates the following result.