Classes Basics
Contents
Introduction
This chapter examines some of the basic features of classes.Reference
A reference is a handle to an object. It "points" to the object created on the heap. Anything created with the keyword "new" will return an object.File: Reference.java
interface PersonInterface { public int getId() ; } class Person implements PersonInterface { int id ; String firstName ; String laststName ; //a static data member does not need //an instance of an object. It is not //associated with an object. static int NoPersonObjects = 0 ; //Constructor called when creating the object Person() { NoPersonObjects++ ; } public int getId() { return id ; } //A static method is like a global method static int getNoPersonObjects() { //Cannot access class data members //id firstName return NoPersonObjects ; } } public class Reference { public static void incrementPersonId( Person personObject ) { //Any changes made here are made in the object in the heap //and are reflected in the original object personObject.id++ ; } public static void main( String args[] ) { //Compiler will not allow //Person personObject ; //null means there does not exist a value //yet for the personObject1 Person personObject1 = null ; System.out.println( personObject1 ) ; // Can't call a method without an object // getId() //We get a handle/reference but it's not the //raw memory address to the person object. //Person object is created on the heap personObject1 = new Person() ; personObject1.id = 1 ; System.out.println( "personObject.getId(): " + personObject1.getId() ) ; Person personObject2 = new Person() ; personObject2.id = 2 ; incrementPersonId( personObject2 ) ; System.out.println( "personObject2.id: " + personObject2.id ) ; //Using the static method getNoPersonObjects() System.out.println( "static method Person.getNoPersonObjects():" + Person.getNoPersonObjects() ) ; System.out.println( "static method personObject1.getNoPersonObjects():" + personObject1.getNoPersonObjects() ) ; //Using the static data member NoPersonObjects System.out.println( "static data member Person.NoPersonObjects:" + Person.NoPersonObjects ) ; System.out.println( "static data member personObject1.NoPersonObjects:" + personObject1.NoPersonObjects ) ; PersonInterface personInterfaceObject = personObject2 ; //System.out.println( personInterfaceObject.id ) ; //Can call methods defined in the interface System.out.println( personInterfaceObject.getId() ) ; } } C:\WebSite\Learn\2\Java\intro>java Reference null personObject.getId(): 1 personObject2.id: 3 static method Person.getNoPersonObjects():2 static method personObject1.getNoPersonObjects():2 static data member Person.NoPersonObjects:2 static data member personObject1.NoPersonObjects:2 3At the top of this class we have defined an interface. An interface has just the method declarations and not the definition. A class can implement an interface and we can construct class objects and assign them to interface variables. A class can implement multiple interfaces. It allows for a more flexible scheme in our OOP. Normally we will not be creating just a single class but multiple classes, interfaces that will be working together. Take the "Vector" class in "java.util" package. It implements the following interfaces: "Serializable, Cloneable, Iterable
The "Person" class has data members, methods. If we create an object we get a new copy of the data members every time.
personObject1 = new Person() ;
personObject1.id = 1 ;
System.out.println( "personObject.getId(): " +
personObject1.getId() ) ;
Person personObject2 = new Person() ;
personObject2.id = 2 ;
We have 2 objects "personObject1" and "personObject2" and each one
has their own copy of the "id" data member. However a static data member
has only 1 copy regardless of how many object of the class are created.
We can think of static data members as global members. In order to access the
static data member/methods we can use the "." notation with either the
class name or an object name.
//Using the static data member NoPersonObjects
System.out.println( "static data member Person.NoPersonObjects:" +
Person.NoPersonObjects ) ;
System.out.println( "static data member personObject1.NoPersonObjects:" +
personObject1.NoPersonObjects ) ;
PersonInterface personInterfaceObject = personObject2 ;
//System.out.println( personInterfaceObject.id ) ;
//Can call methods defined in the interface
System.out.println( personInterfaceObject.getId() ) ;
We create a Person object using a special method called the constructor.
personObject1 = new Person() ;The "new Person()" causes the constructor of the Person class to be called and in turn increments the static data member "NoPersonObjects" . This data member keeps track of how many "Person" objects are created in our program. We print this value at the end of the program and see that the value is 2 indicating that Person 2 objects got created during the duration of the program.
We can pass the object as an argument to another function:Person personObject2 = new Person() ; personObject2.id = 2 ; incrementPersonId( personObject2 ) ;The "personObject2" is a reference and we pass it to the method "incrementPersonId". Java has pass by value and what that means is the reference is copied by value in the method:public static void incrementPersonId( Person personObject )The "personObject" in the method now contains the reference and any changes made inside the method are reflected back in the calling function of "main" .System.out.println( "personObject2.id: " + personObject2.id ) ; personObject2.id: 3 Change is reflected after calling the incrementPersonId method.We can also assign a "Person" object to an interface object that it implements.PersonInterface personInterfaceObject = personObject2 ;We can now invoke the methods of the interface. The "Person" class must implement all the methods of the interface else we will get a compiler error when compiling "Person.java" .
Exercise 1. What does the below file print ?
File: PassByValue.java
public class PassByValue { public static void changeValues( int i1 , int i2 ) { i1 = 21 ; i2 = 22 ; } public static void main(String[] args) { int x1 = 10 ; int x2 = 11 ; changeValues( x1 , x2 ) ; System.out.println( x1 ) ; System.out.println( x2 ) ; } }single object hierarchy
In Java all classes whether explicity or implicitly derive from the class "Object".This is called a single object hierarchy.
File: SingleHierarchy.java
class Person { int id ; String firstName ; String laststName ; } class AnotherPerson { int id ; String firstName ; String lastName ; public void setValue(int idP) { id = idP ; } public void setValue(int idP, String firstNameP ) { id = idP ; firstName = firstNameP ; } public void setValue(int idP , String firstNameP , String lastNameP ) { id = idP ; firstName = firstNameP ; lastName = lastNameP ; } public String toString() { return( "id: " + id + " Name: " + firstName + " " + lastName ) ; } } public class SingleHierarchy { public static void main( String args[] ) { Person personObject1 = new Person() ; //Uses the Object class toString method System.out.println( personObject1 ) ; System.out.println( Integer.toHexString(personObject1.hashCode()) ) ; AnotherPerson personObject2 = new AnotherPerson() ; //Method Overloading personObject2.setValue( 1 ) ; personObject2.setValue( 1 , "Jack" ) ; personObject2.setValue( 1 , "Jack" , "Dempsey" ) ; //Uses the AnotherPerson class toString method //Method Overriding System.out.println( personObject2 ) ; } } C:\WebSite\Learn\2\Java\intro>java SingleHierarchy Person@15db9742 15db9742 id: 1 Name: Jack Dempsey in the below code: Person personObject1 = new Person() ; //Uses the Object class toString method System.out.println( personObject1 ) ;The JDK is using the "toString()" method of the Object class to print the object. This prints the class of the name and the hashcode. In the next line we call "hashCode()" which is another method of the Object class. We have 2 important concepts for methods "overriding" and "overloading" . Method "overriding" applie to an inherited class when it's method has the same signature as the base method. Method "overloading" is the ability to have methods by the same name that differ in their arguments.
The "setValue()" method has 3 variations differeing in the number of arguments passed to it. We also have another class "AnotherPerson" that has the "toString()" method that overrides the "Object toString()" method and doing a "println" invokes the method and we get more readable output.
Another method that "Object" has is the "equals" method. We do have the "==" comparator that compares 2 objects. If the objects are the same ( have the same references ) then it return true else it returns false. The "Object" class has an "equals" method that does the same comparision as "==". However we can change that by overriding it.
File: Equals.java
class Person { int id ; String firstName ; String laststName ; } class AnotherPerson { int id ; String firstName ; String lastName ; public boolean equals( AnotherPerson obj1 ) { return( id == obj1.id ) ; } } public class Equals { public static void main( String args[] ) { Person personObject1 = new Person() ; personObject1.id = 1 ; Person personObject2 = new Person() ; personObject2.id = 1 ; System.out.println( personObject1 == personObject1 ) ; System.out.println( personObject1 == personObject2 ) ; //By default equals works like == System.out.println( personObject1.equals( personObject1) ) ; System.out.println( personObject1.equals( personObject2 ) ) ; AnotherPerson personObject3 = new AnotherPerson() ; personObject3.id = 1 ; AnotherPerson personObject4 = new AnotherPerson() ; personObject4.id = 1 ; System.out.println( "---------------" ) ; //Works as before System.out.println( personObject3 == personObject3 ) ; System.out.println( personObject3 == personObject4 ) ; //Custom behavior System.out.println( personObject3.equals( personObject4) ) ; System.out.println( personObject3.equals( personObject4 ) ) ; } } C:\WebSite\Learn\2\Java\intro>java Equals true false true false --------------- true false true true
Exercise 2.Read about the Object class methods at: https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Object.html Examine the source code for the Object class and check the "equals" method.