This chapter covers writing custom classes. Although Java provides an extensive library of predefined classes, the ability to write custom classes is essential to represent programmers’ own ideas. Review chapter 18 “Using Objects.”
Class Declaration
![](https://precollegejava.wordpress.com/wp-content/uploads/2022/08/c26-1.png?w=600)
Modifier defines who has access to the class. A class modifier can be public
or default. A public
class can be accessed by all. A default class (the class without a modifier) can be accessed only by classes in the same “package”. Java package is a group of related classes.
The keyword Class
indicates that the code block within curly braces {}
is a class declaration.
Class_Name, by convention, begins with an uppercase letter. Java class name and the source code filename should match.
Anatomy of Class
Class is a formal specification of an object. It includes attributes that define what an object is, methods that define what an object does, and constructors that define how an object is instantiated.
Attributes
The attributes of an object are represented by “instance variables” in the class declaration. Instance variables are usually declared with private
modifier to prevent inadvertent changes.
BumperCar.java
public class BumperCar {
int number; // public attribute
String color; // public attribute
}
Point.java
public class Point {
private int x; // private attribute
private int y; // private attribute
}
Main program
class Main {
public static void main(String[] args) {
BumperCar myCar = new BumperCar();
System.out.println(myCar.color); // ok
Point myPoint = new Point();
System.out.println(myPoint.x); // error
}
}
Line 4 – Attribute color
has public access. So, this prints the value of color
.
Line 7 – Attribute x
has private access. So, this statement results in error.
Constructors
The constructors initialize the state of an object at the time of object creation.
![](https://precollegejava.wordpress.com/wp-content/uploads/2022/08/c26-5.png?w=600)
Constructor has the same name as the class name. public
modifier allows the constructor to be invoked at the time of object instantiation.
A constructor may have zero or more parameters.
A constructor doesn’t have a return type, not even void
.
Default Constructor
The constructor with no parameter is called the “default constructor”. In the default constructor, the instance variables are initialized with default values.
public class Point {
private int x; // private attribute
private int y; // private attribute
// default constructor
public Point() {
x = 0; // default value
y = 0; // default value
}
}
Overloaded Constructors
A constructor is said to be overloaded when there exist multiple constructors. Each constructor has the same name (the class name) but different parameters.
public class Point {
private int x; // private attribute
private int y; // private attribute
// default constructor
public Point() {
x = 0; // default value
y = 0; // default value
}
// overloaded constructor
public Point(int a, int b) {
x = a; // assign parameter a
y = b; // assign parameter b
}
}
No Constructor
A class declaration may not include any constructor. In this case, Java provides a default constructor where instance variables are initialized with default values. Note, however, the default value may not be the value you intend for the instance variable. Java initializes int
data type to 0
and String
data type to null
.
Lamp.java
public class Lamp {
int height; // public attribute
String color; // public attribute
// no constructor
}
Main program
class Main {
public static void main(String[] args) {
Lamp deskLamp = new Lamp();
System.out.println(deskLamp.height); // 0
System.out.println(deskLamp.color); // null
}
}
Line 4 – Attribute height is int
type. Java sets the default value to 0
.
Line 5 – Attribute color is String
type. Java sets the default value to null
.
Note: Default constructor is required if there exists a constructor with parameter(s).
Constructor with Object Parameter
A constructor may have a reference type as formal parameter. In other words, you can pass-in an object as parameter to a constructor call.
Lamp deskLamp = new Lamp();
Lamp floorLamp = new Lamp(deskLamp);
In this case, you want to write the constructor so that the instance variables are initialized with the copy of the reference object. Take care not to modify the original object.
Lamp.java
public class Lamp {
int height; // public attribute
String color; // public attribute
// default constructor
public Lamp() {
height = 3;
color = "yellow";
}
// overloaded constructor
public Lamp(Lamp myLamp) {
height = myLamp.height; // copy of myLamp height
color = myLamp.color; // copy of myLamp color
}
}
Main program
class Main {
public static void main(String[] args) {
Lamp deskLamp = new Lamp();
Lamp floorLamp = new Lamp(deskLamp);
System.out.println(deskLamp.color); // yellow
System.out.println(floorLamp.color); // yellow
}
}
Line 3 – Lamp object deskLamp
is created by invoking the default constructor.
Line 4 – Lamp object floorLamp
is created by invoking the overloaded constructor which copies the attributes of
to deskLamp
.floorLamp
This Keyword
Take a look at the formal parameters in the overloaded constructor. The parameters have the same identifier as the instance variables.
public class Point {
// instance variables
private int x = 0;
private int y = 0;
// default constructor
public Point() {
x = 1;
y = 1;
}
// overloaded constructor
public Point(int x, int y) {
x = x; // assign 0
y = y; // assign 0
}
}
In this case, Java assumes the x
and y
on the right-hand side of the assignment operator (=) to be the instance variables. So, this constructor assigns the instance variable with their current values. The parameter values are never used.
To avoid confusion, use this
keyword to differentiate the instance variable from the formal parameter.
// overloaded constructor
public Point(int x, int y) {
this.x = x; // assign parameter x
this.y = y; // assign parameter y
}
Alternatively, use different identifiers for the formal parameters.
// overloaded constructor
public Point(int a, int b) {
x = a; // assign parameter a
y = b; // assign parameter b
}
Methods
When instance variables are declared private, the outside classes cannot access them directly. They need to use the class methods. The methods that return the current values of the instance variables are called accessor methods. The methods that modify the current value of the instance variables are called mutator methods.
Point.java
public class Point {
// instance variables
private int x;
private int y;
// default constructor
public Point() {
x = 0;
y = 0;
}
// overloaded constructor
public Point(int a, int b) {
x = a;
y = b;
}
// accessor method
public int getX() {
return x;
}
// accessor method
public int getY() {
return y;
}
// mutator method
public void setX(int n){
x = n;
}
// mutator method
public void setY(int n){
y = n;
}
}
Main program
class Main {
public static void main(String[] args) {
Point p1 = new Point();
String point = "("+ p1.getX() + "," + p1.getY() + ")";
System.out.println(point); // (0,0)
p1.setX(2);
p1.setY(3);
point = "("+ p1.getX() + "," + p1.getY() + ")";
System.out.println(point); // (2,3)
}
}
Line 3 – p1 invokes the default constructor which creates an instance of Point object (0,0)
Line 4 – Uses the accessor methods getX()
and getY()
to get the current value of x
and y
.
Lines 7 and 8 – Uses the mutator methods setX()
and setY()
to change the current value of x
and y
.
toString Method
Notice how we had to use the string concatenation to print a Point object.
String point = "("+ p1.getX() + "," + p1.getY() + ")";
System.out.println(point);
Wouldn’t it be nice if we can simply pass the object reference to the print method just as we do with primitive type and String type?
We can achieve this with toString()
method. The method name must be “toString” and must return a String value.
Point.java
public class Point {
. . .
public String toString() {
return "(" + x + "," + y + ")";
}
}
BumperCar.java
public class BumperCar {
. . .
public String toString() {
return color + " car number " + number;
}
}
Main program
class Main {
public static void main(String[] args) {
BumperCar myCar = new BumperCar();
System.out.println(myCar);
Point myPoint = new Point();
System.out.println(myPoint);
}
}
Line 7 – The print method attempts to convert the Point object to string by invoking the toString()
method. The method returns a string which is used by the print method to output to screen.
Line 10 – Similarly, the print attempts to convert the BumperCar object to string by invoking the toString()
method. The method returns a string which is used by the print method to output to screen.
This is output.
purple car number 12
(0,0)
If an object does not include toString()
method, the toString()
method from the Object class is inherited. The Object class is the topmost level class in that all classes inherit from it. The toString()
method from the Object class is generic, so it usually doesn’t return the value we’d expect.
Example
class Main {
public static void main(String[] args) {
Lamp myLamp = new Lamp();
System.out.println(myLamp);
}
}
Line 4 – Lamp class does not have toString()
method. So, it is inherited from the Object class.
This is output.
Lamp@7699a589
Apparently, this is the memory address of the Lamp object. This is not how we want to print a Lamp objects. We had better write our own toString()
method.
public class Lamp {
. . .
public String toString() {
return height + " feet " + color + " lamp";
}
}
Now the main program outputs this.
3 feet yellow lamp
In-Depth Knowledge
Scope and Access
Top level classes use the modifier public
or default (i.e., no modifier). A class declared with public
modifier can be accessed by all. A driver class contains the main program that uses the public classes.
![](https://precollegejava.wordpress.com/wp-content/uploads/2022/08/c26-2.png?w=500)
Class declared with no modifier can be accessed only by the classes in the same package.
![](https://precollegejava.wordpress.com/wp-content/uploads/2022/08/c26-3.png?w=500)
Class can be nested. An inner class is the class declared within another class. The class that contains the inner class is called outer class or top-level class. The inner class can be declared with private
modifier.
![](https://precollegejava.wordpress.com/wp-content/uploads/2022/08/c26-4.png?w=500)
Private Constructor
Not all constructors are public. A constructor can be declared with private
modifier. Private constructor serves special purposes, one of which is a singleton class. A singleton class creates only one instance of its object.
TheCar.java
public class TheCar {
static TheCar car = null; // initial state
public int number; // instance variable
// private constructor
private TheCar() {
number = 12;
}
// create TheCar object
static public TheCar getCar() {
if (car == null) {
car = new TheCar();
}
return car;
}
}
Line 2 – The initial state of TheCar object is set to null
to indicate that no instance of this object has been created yet.
Line 6 – The private
constructor cannot be invoked from outside of TheCar class declaration.
Line 12 – Since the constructor is private, we need to provide an alternate way to create TheCar object. The method getCar()
creates the object only when the state is null
.
Line 15 – Once TheCar object is created, the state is no longer null
. Hence, TheCar object that’s been created once is returned over and over again.
Main program
class Main {
public static void main(String[] args) {
TheCar car1 = TheCar.getCar();
TheCar car2 = TheCar.getCar();
System.out.println("Car1: " + car1.number); // 12
car1.number = 3; // change car number
System.out.println("Car1: " + car1.number); // 3
System.out.println("Car2: " + car2.number); // 3
}
}
Line 3 – Since TheCar object has not been created before, getCar()
method creates an instance of TheCar object. car1
refers to this object.
Line 4 – Since TheCar object has been created once, getCar()
method returns the current object. car2
refers to the same object as car1
.
![](https://precollegejava.wordpress.com/wp-content/uploads/2022/08/c26-6.png?w=340)
Line 7 – car1
object’s number is changed to 3.
Line 9 – car2
object’s number is 3 since it’s referring to the same object as car1
.
2022 Copyright