Classes and Objects I
- Contents
- Review of Instance Fields and Methods
- Static Class Members
- Static Fields
- Static Methods
- Passing Objects as Arguments
- Returning Objects from Methods
- The
toString
Method - The
equals
Method - Methods that Copy Objects
Review of Instance Fields and Methods
Each instance of a class has its own copy of instance variables.
Example:
- A
Rectangle
class defines alength
and awidth
field. - Each instance of the
Rectangle
class can have different values stored in itslength
andwidth
fields.
- A
Instance methods require that an instance of a class be created in order to be used.
Instance methods typically interact with instance fields or calculate values based on those fields.
Static Class Members
Static fields and static methods do not belong to a single instance of a class.
To invoke a static method or use a static field, the class name, rather than the instance name, is used.
Example:
// Math is the class name. // sqrt is the static method. double val = Math.sqrt(25.0);
Static Fields
Class fields are declared using the
static
keyword between the access specifier and the field type.private static int count = 0;
The field is initialized to
0
only once, regardless of the number of times the class is instantiated.- primitive static fields are initialized to
0
if no initialization is performed.
- primitive static fields are initialized to
Book example:
Countable.java
StaticDemo.java
- Multiple instances refer to the one and only one copy of static data.
- Referring to a static fields through object instances generates a warning.
Example code:
public class Program { public static void main(final String[] args) { // The getCount method is accessible without // creating an instance of the Counter class. System.out.println("count: " + Counter.getCount()); // Create three instances. final Counter c1 = new Counter(); final Counter c2 = new Counter(); final Counter c3 = new Counter(); // Warning: The static method getCount() from // the type Counter should be accessed in a // static way. System.out.println("count 1: " + c1.getCount()); System.out.println("count 2: " + c2.getCount()); System.out.println("count 3: " + c3.getCount()); } } class Counter { private static int count; public static int getCount() { return count; } }
Static Methods
Methods can also be declared static by placing the
static
keyword between the access modifier and the return type of the method.class Metric { public static double milesToKilometers(double miles) { :
When a class contains a static method, it is not necessary to create an instance of the class in order to use the method.
double kilometers = Metric.milesToKilometers(1.0);
They are typically used to create utility classes, such as the
Math
class in the Java standard library.Static methods may not directly access instance fields, only the static fields.
- Compiling Error: "Cannot make a static reference to the non-static field"
Example code:
public class Program { public static void main(final String[] args) { System.out.println( "10 cm is " + Metric.centisToMillis(10.0) + " mm"); final Metric instance = new Metric(); // Warning: The static method // centisToMillis(double) from the // type Metric should be accessed in // a static way. System.out.println( "10 cm is " + instance.centisToMillis(10.0) + " mm"); } } class Metric { public static double centisToMillis( final double centis) { return 10.0 * centis; } }
Passing Objects as Arguments
Objects can be passed to methods as arguments.
Java passes all arguments by value.
When an object is passed as an argument, the value of the reference variable is passed.
The value of the reference variable is an address or reference to the object in memory.
A copy of the object is not passed, just a pointer to the object.
When a method receives a reference variable as an argument, it is possible for the method to modify the contents of the object referenced by the variable.
Example code:
public class Program { public static void main(final String[] args) { final Person personA = new Person(9.0); final Person personB = new Person(7.0); if (personA.compareTo(personB) > 0) System.out.println( "PersonA is taller than PersonB."); } } final class Person { public final double height; public Person(final double height) { this.height = height; } // Returns -1 if this instance is shorter // than the other instance, +1 if this // instance is taller than the other instance, // or zero if the two instances are the same // height. public int compareTo(final Person other) { return this.height < other.height ? -1 : this.height > other.height ? 1 : 0; } }
Returning Objects from Methods
Methods are not limited to returning the primitive data types.
Methods can return references to objects as well.
Just as with passing arguments, a copy of the object is not returned, only its address.
-
Book example:
Example code:
public class Program { public static void main(final String[] args) { final Person parent1 = new Person(4.0); final Person parent2 = new Person(10.0); final Person child = Person.spawn(parent1, parent2); System.out.println( "child height: " + child.height); } } final class Person { public final double height; public Person(final double height) { this.height = height; } public static Person spawn( final Person parent1, final Person parent2) { // Calculate the average of the two // heights and return a new instance // with that value. final double average = 0.5 * (parent1.height + parent2.height); return new Person(average); } }
The toString
Method
The
toString
method of a class can be called explicitly.The
toString
method, however, does not have to be called explicitly but is called implicitly whenever an object of the class is passed toprintln
orprint
.The
toString
method is also called implicitly whenever an object of the class is concatenated to a string.All objects have a
toString
method that returns the class name and a hash of the memory address of the object.Person instance = new Person(3.0); System.out.println(instance); // This prints something like: // Person@199a0c7c
We can override the default method with our own to provide more useful information.
-
Book example:
Example code:
public class Program { public static void main(final String[] args) { final Person person = new Person(10.0); // Call toString() explicitly from println. System.out.println(person.toString()); // Call toString() implicitly from println. System.out.println(person); // Call toString() implicitly when // concatenating a Person instance with // a string. final String text = "This person's height is " + person + "."; System.out.println(text); } } final class Person { public final double height; public Person(final double height) { this.height = height; } @Override public String toString() { return "approximately " + this.height + " units"; } }
The equals
Method
When the
==
operator is used with reference variables, the memory address of the objects are compared.All objects have an
equals
method.The default operation of the
equals
method is to compare memory addresses of the objects.- The default behavior is the same as the
==
operator.
- The default behavior is the same as the
Objects can be compared by their contents rather than by their memory addresses.
-
Book example:
Example code:
public class Program { public static void main(final String[] args) { final Person personA = new Person(10.0); final Person personB = new Person(10.0); System.out.println( "personA == personB --> " + (personA == personB)); System.out.println( "personA 'equals' personB --> " + personA.equals(personB)); } } final class Person { private final double height; public Person(final double height) { this.height = height; } @Override public boolean equals(final Object o) { // Check the other instance is not null. if (null == o) return false; // Check symmetry. if (!(o instanceof Person)) return false; // Check reflexivity. if (this == o) return true; // Check the fields are equal. final Person rhs = (Person)o; return this.height == rhs.height; } @Override public int hashCode() { return Double.valueOf(this.height).hashCode(); } }
Methods that Copy Objects
We cannot use the assignment operator,
=
, to copy an objectThere are two ways to copy an object.
Reference only copy
- This is simply copying the address of an object into another reference variable.
Deep copy, correct
- This is involves creating a new instance of the class and copying the values from one object into the new object.
-
Book example:
A copy constructor accepts an existing object of the same class and clones it.
Example code:
public class Program { public static void main(final String[] args) { // Create ONE instance and assign it to // TWO variables. final Person personA = new Person(10.0); final Person personB = personA; // Setting the height of EITHER variable // sets the height of the ONE instance. personB.setHeight(20.0); System.out.println("personA --> " + personA); System.out.println("personB --> " + personB); // Use a copy constructor to create a // third, unique instance. final Person personC = new Person(personA); // Setting the height of this instance // does not affect the others. personC.setHeight(30.0); System.out.println("personA --> " + personA); System.out.println("personC --> " + personC); } } class Person { private double height; public Person(final double height) { this.height = height; } public Person(final Person other) { this.height = other.getHeight(); } public double getHeight() { return this.height; } public void setHeight(final double height) { this.height = height; } @Override public String toString() { return Double.toString(this.height); } }