Instance Creation
Home ] Up ] What is a Class? ] What is an Instance? ] Class Members ] Methods and Overloading ] [ Instance Creation ] Instance Destruction ] Finalizers ] Class Variables and Methods ] Wrapper Classes ]

 

 

As we said earlier, we can create an instance (object) by using:

new Circle();

which uses:

  • the new operator to allocate space for the instance
  • a constructor to initialize the instance

What is a constructor?

  • It is a special method
  • Its name is the same as the class name (case-sensitive)
  • It may have zero or more arguments (just like regular methods)
  • It has no explicit return type
  • It must not use a return type of void
  • It may appear that the constructor returns an instance of its class, but in fact, it's the new operator that does that.
  • It must not use a return statement to return a value
  • Strangely, a constructor is not a member of its class

Implicit and Explicit Constructors

Remember that, in our class Circle, we had:

import java.lang.Math;

public class Circle
{
    // Accessor methods
    public double getX()      { return m_x; }
    public double getY()      { return m_y; }
    public double getRadius() { return m_r; }
    // Mutator methods
    public void setX(double v)      { m_x = v; }
    public void setY(double v)      { m_y = v; }
    public void setRadius(double r) { m_r = r; }
    // Operations/Attributes
    public double getCircumference()
                { return 2 * Math.PI * m_r; }
    public double getArea()
                { return Math.PI * m_r*m_r; }

    double m_x, m_y; // coordinates of center
    double m_r; // radius
}

So where are the constructors in this Circle class?

Answer: There are no explicit constructors, only implicit ones.  

The Default Constructor

If a class has no explicitly specified constructors, then a default constructor is automatically generated for that class by the Java compiler

  • A default constructor is a constructor that takes zero arguments
  • It is sometimes called a no-argument (or no-arg) constructor)
  • In the case of the above Circle class, the default constructor does nothing obvious (note that the class fields will be automatically initialized to zero values).
  • If you wish to write some explicitly specified constructors and a no-argument constructor for a class, you must write the no-argument constructor yourself.

Multiple Constructors

Sometimes, you need to initialize class instances in different ways. So:

  • A class may have more than one constructor
  • Because each constructor must have the exact same name as the class name, each separate constructor is therefore an overloaded method with a different signature (overloaded just like regular methods)

For example:

public class Circle
{
    // Constructors
    public Circle(double x, double y, double r)
    { m_x = x; m_y = y; m_r = r; }

    public Circle(double r) 
    { m_x = 0.0; m_y = 0.0; m_r = r; }

    public Circle(Circle c)
    { m_x = c.m_x; m_y = c.m_y; m_r = c.m_r; }

    public Circle()
    { m_x = m_y = m_r = 0.0; }
     
     // Accessor methods
    public double getX()      { return m_x; }
    public double getY()      { return m_y; }
    public double getRadius() { return m_r; }
    // Mutator methods
    public void setX(double v)      { m_x = v; }
    public void setY(double v)      { m_y = v; }
    public void setRadius(double r) { m_r = r; }
    // Operations/Attributes
    public double getCircumference()
                { return 2 * Math.PI * m_r; }
    public double getArea()
                { return Math.PI * m_r*m_r; }

    double m_x, m_y; // coordinates of center
    double m_r; // radius
}

this()

But there's a better way to write this, to avoid code repetition:

The first statement of a constructor may be an explicit call to another constructor of the same class, using the syntax:
this( /* arguments */ );

For example:

public class Circle
{
    // Constructors
    public Circle(double x, double y, double r)
    { m_x = x; m_y = y; m_r = r; }
    public Circle(double r) 
    { this(0.0, 0.0, r); }
    public Circle()
    { this(0.0, 0.0, 0.0); }

     // Accessor methods
    public double getX()      { return m_x; }
    public double getY()      { return m_y; }
    public double getRadius() { return m_r; }
    // Mutator methods
    public void setX(double v)      { m_x = v; }
    public void setY(double v)      { m_y = v; }
    public void setRadius(double r) { m_r = r; }
    // Operations/Attributes
    public double getCircumference()
                { return 2 * Math.PI * m_r; }
    public double getArea()
                { return Math.PI * m_r*m_r; }

    double m_x, m_y; // coordinates of center
    double m_r; // radius
}

In this way, you can write a constructor whose code is shared among other constructors -- no need to cut and paste code!

"Copy Constructors"

In C++, there is another kind of constructor that is commonly defined -- a copy constructor, which is usually of the form:
Circle(const Circle &c)	// This is valid C++, but invalid Java
In C++, a copy constructor is automatically generated for you for each class that does not include an explicitly written copy constructor. (C++ also automatically generates an assignment operator for each class that does not include an explicitly written assignment operator.) 
  • The generated copy constructor does a member-wise (shallow) copy.
  • In some cases, this is incorrect behavior, and will get you into serious trouble.
  • In other cases, you don't want a copy constructor at all, because it doesn't make sense for your particular class.
  • C++ copy constructors can cause a lot of trouble.
  • If you don't want C++ to generate a copy constructor for you, or if you want to write your own copy constructor, you have to explicitly write your own copy constructor.

In Java, you can also create a copy constructor:

Circle(Circle c)

but Java will not automatically generate one for you.

If you want a copy constructor for a Java class, you must write one yourself.

For example:

public class Circle
{
    // Constructors
    public Circle(double x, double y, double r)
    { m_x = x; m_y = y; m_r = r; }
    public Circle(double r) 
    { this(0.0, 0.0, r); }
    public Circle()
    { this(0.0, 0.0, 0.0); }
    public Circle(Circle c)
    { this(c.m_x, c.m_y, c.m_r); }

     // Accessor methods
    public double getX()      { return m_x; }
    public double getY()      { return m_y; }
    public double getRadius() { return m_r; }
    // Mutator methods
    public void setX(double v)      { m_x = v; }
    public void setY(double v)      { m_y = v; }
    public void setRadius(double r) { m_r = r; }
    // Operations/Attributes
    public double getCircumference()
                { return 2 * Math.PI * m_r; }
    public double getArea()
                { return Math.PI * m_r*m_r; }

    double m_x, m_y; // coordinates of center
    double m_r; // radius
}

This is not normally done.

Note: The proper way to do this in Java is to use clone() -- more on cloning, later.

 

This page was last modified on 02 October, 2007