Class Constructors in Java

 


Constructors are setup methods that classes have. The constructor gets called into action automatically when an object is created and is used to initialize the properties of the object- set the objects start values. You probably noticed in my last tutorial that my class did not have a constructor method. And that worked, because Java is cool enough to supply us with a default constructor should we forget to write our own.

When writing a constructor, it must have the same name as the class and no return type- not even void.

Lets look at some code...


public class Rectangle {
  
  private int length;
  private int width;
  private int area;

  //a constructor
  public Rectangle (int l, int w) {
    length = l;
    width = w;
    area = l * w;
  }

  //a getter
  int getArea() {
    return area;
  }
 
} //Rectangle

You can see the public method called Rectangle that takes two arguments and uses them to set the class's properties. And here is how we would use the constructor in our main program...


public class MainClass {

  public static void main(String[] args) {

    Rectangle myRect = new Rectangle(2, 3);
  
    System.out.println(myRect.getArea());
   
  } //main
} //MainClass

With our new constructor we have to supply the start values we want. The following code is no longer valid...


public class MainClass {

  public static void main(String[] args) {

    Rectangle myRect = new Rectangle();
  
    System.out.println(myRect.getArea());
   
  } //main
} //MainClass

It produces an error.

  required: int,int
  found:    no arguments
  reason: actual and formal argument lists differ in length

But didn't Java supply us with a default constructor? Yes it did, until we decided to define a constructor of our own. Now we don't get a default constructor anymore. Thanks for leaving us in the lurch Java... But you know what, we can define our own default constructor, by overloading our constructor. There are a few ways to do this...

This would be the traditional way...


public class Rectangle {
  
  private int length;
  private int width;
  private int area;

  //a constructor
  public Rectangle (int l, int w) {
    length = l;
    width = w;
    area = l * w;
  }

  //a default constructor
  public Rectangle() {
    length = 3;
    width = 5;
    area = 15;
  }

  //a getter
  int getArea() {
    return area;
  }
 
} //Rectangle

This next technique uses inline initialization...


public class Rectangle {
  
  //inline initialization
  private int length = 3;
  private int width = 5;
  private int area = 15;

  //a constructor
  public Rectangle (int l, int w) {
    length = l;
    width = w;
    area = l * w;
  }

  //a default constructor using the inline values
  public Rectangle() {
    
  }

  //a getter
  int getArea() {
    return area;
  }
 
} //Rectangle

It can be used to reduce your code size a little bit.
Another trick is called constructor chaining...


public class Rectangle {
  
  private int length;
  private int width;
  private int area;

  //a constructor
  public Rectangle (int l, int w) {
    length = l;
    width = w;
    area = l * w;
  }

  //a default constructor makes a call to the other constructor
  public Rectangle() {
    this(3, 5);
  }

  //a getter
  int getArea() {
    return area;
  }
 
} //Rectangle

Lets talk a little bit about the keyword this. But first consider this code...


public class Rectangle {
  
  private int length;
  private int width;
  private int area;

  //a constructor
  public Rectangle (int length, int width) {
    length = length;
    width = width;
    area = length * width;
  }

  //a default constructor makes a call to the other constructor
  public Rectangle() {
    this(3, 5);
  }

  //a getter
  int getArea() {
    return area;
  }
 
} //Rectangle

That code creates a very sneaky bug which can be hard for beginners to catch. It compiles fine and even produces the expected output, or so you might think. But what is the problem? Lets look again...


public class Rectangle {
  
  private int length;
  private int width;
  private int area;

  //a constructor
  public Rectangle (int length, int width) {
    length = length;
    width = width;
    area = length * width;
  }

  //a default constructor makes a call to the other constructor
  public Rectangle() {
    this(3, 5);
  }

  //a getter
  int getArea() {
    return area;
  }
 
} //Rectangle

In the constructor, the compiler thinks that length and width refer to the parameters and not the class properties. So the properties of length and width never get initialized. But area does get initialized and so the output passes, at least at first. But if you tried to get the value of length or width you would see that they have a value of 0, since Java will assign an uninitialized int a value of 0. So the area of a rectangle with length of 0 and width of 0 should be 0. Right? This is where the keyword of this becomes important. It makes a distinction between the parameter name and the class property. Here is the correct way to fix the code.


public class Rectangle {
  
  private int length;
  private int width;
  private int area;

  //a constructor
  public Rectangle (int length, int width) {
    this.length = length;
    this.width = width;
    area = length * width;
  }

  //a default constructor makes a call to the other constructor
  public Rectangle() {
    this(3, 5);
  }

  //a getter
  int getArea() {
    return area;
  }
 
} //Rectangle

I hope you have found this tutorial helpful. Thank you for reading.

Comments

Popular Posts