Programming Java

An Introduction to Computer Science



26. Writing Classes

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

Figure 26A – Class Declaration

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.

Figure 26B – Constructor Syntax

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 deskLamp to 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.

Figure 26C – Public access

Class declared with no modifier can be accessed only by the classes in the same package.

Figure 26D – Classes within package

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.

Figure 26E – Private Class

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.

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


By:


Design a site like this with WordPress.com
Get started