Table of Contents
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, and play games with it..
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.
