Aqua Phoenix
     >>  Lectures >>  Java 2  
 

Navigator
   
 
       
   

2.2 Object - Example

For illustrative purposes, we create and improve on the design of a class.

Person.java

public class Person {

  String name;
  int age;

  public void printInfo() {

    System.out.println("Name: " + name + ", Age: " + age);
  }
}
We make a few observations:
  • The class contains 2 variables and one method.
  • Variables name and age are accessible for viewing and editing from outside of the class.
  • Method printInfo() is also accessible from outside the class.
  • There is no formal constructor, and hence the default constructor which creates an instance of this class must be used. (more on this later)

We also create a class from which objects of type Person will be instantiated:

PersonTest.java

public class PersonTest {

  public static void main(String[] args) {

    Person john;
    john = new Person();
    Person mike = new Person();

    john.name = "John";
    john.age = 20;
    mike.name = "Mike";

    john.printInfo();
    mike.printInfo();
  }
}
We note:
  • Class PersonTest has one method, which happens to be the method called by the Java Virtual Machine when running this class.
  • 2 instances of class Person are instantiated
  • Person is instantiated with the default constructor which takes no arguments: new Person()
  • There exist references to member variables in the instantiated objects, e.g. john.name
  • There exist references to member methods in the instantiated objects, e.g. john.printInfo()

The output of the above program is:

Name: John, Age: 20
Name: Mike, Age: 0
Internally, the instantiation of object john sets aside a piece of memory, in which the data for the object is placed. Secondly, the separate instantiation of object mike sets aside a different piece of memory. Essentially, there are now 2 references to separate addresses in memory, which hold the data for the 2 objects.

Had our course of action been the following instead, then the output would have been the same:

public class PersonTest {

  public static void main(String[] args) {

    Person x;
    x = new Person();

    x.name = "John";
    x.age = 20;
    x.printInfo();

    x = new Person();
    x.name = "Mike";
    x.printInfo();
  }
}
However, the two different implementations of PersonTest behave differently. While the first instantiates 2 objects of class Person and assigns them to separate names, the seoncd implementation instantiates 2 objects and assigns them to the same name. This has the effect of removing the initial reference of x to a Person object for John, and re-assigning it to a Person object for Mike. The now reference-less object John is eventually removed by the automatic Garbage Collector, which does not require the developer to keep track of freeing memory.

The example of Student.java above has a few faults. We can, for example, create a new Person object and assign a negative age:

Person alex = new Person();
alex.age = -800;
Instead of revealing the variables for an object and allowing outside classes to change the values, methods inside the class should verify the data and react accordingly. A better version of Person.java is:

public class Person {

  private String name;
  private int age;


  public void setName(String n) {

    name = n;
  }


  public void setAge(int years) {

    if (years < 0) {
      System.err.println("Age passed is negative! Kept previous value");
    } else {
      age = years;
    }
  }


  public String getName() {

    return name;
  }


  public int getAge() {

    return age;
  }


  public void printInfo() {

    System.out.println("Name: " + name + ", Age: " + age);
  }
}
This new version checks for negative values of age, and also implements methods for setting and returning particular values of this object. Variables are now protected using the specifier private, so that no external class can modify these values directly.

To instantiate an object of class Person, we will change PersonTest.java:

public class PersonTest {

  public static void main(String[] args) {

    Person john = new Person();
    john.setName("John");
    john.setAge(20);

    Person mike = new Person();
    mike.setName("Mike");
    mike.setAge(-92);
    mike.setAge(25);

    john.printInfo();
    mike.printInfo();
  }
}
The output is accordingly:

Age passed is negative! Kept previous value
Name: John, Age: 20
Name: Mike, Age: 25

2.2.1 Encapsulation

The process of protecting variables by declaring them as private, and allowing reading and modification of the variable through methods only is termed Encapsulation.