Lecture : Object Oriented Programming Concepts in Java
In the previous lecture:
In this lecture:
Java Classes and Objects
The basic elements of a Java program are classes created as part of abstraction hierachies (as discussed in lecture 1b).
A class is a named collection of:
You cannot write Java programs without defining classes! All Java statements must be part of methods and all methods must be part of classes.
Every new class that we define creates a new data type within our program. These data types are "moulds" that represent the kinds of things that can possibly exist in our program. The classes are not objects... they are only the moulds or kinds for objects.
Here is the syntax for the specification of a class Point2D.
/** Point2D represents a Cartesian point in 2 dimensions */ public class Point2D { public double xCoordinate; public double yCoordinate; public Point2D(double newX, double newY) { xCoordinate = newX; yCoordinate = newY; } public void Print() { System.out.println("x=" + xCoordinate + " y=" + yCoordinate); } public double distanceFromOrigin() { return Math.sqrt(xCoordinate * xCoordinate + yCoordinate * yCoordinate); } } |
This specification for a new data type Point2D will need to go into a file called Point2D.java
Note:
Making Objects
How do we actually make a Point2D object now that we have defined such a data type?
public class PointTester
{
public static void main(String[] args)
{
// Declare a variable that can (potentially) name a Point2D object
Point2D myPointObject;
// Declare a double (this *does* immediately name an exisiting double value ... doubles are *not* reference objects)
double distance;
// Create a Point2D object and assign myPoint to be a reference to (name for) this Point2D
myPointObject = new Point2D(3.0, -5.0);
// Print out the point object's fields using its Print() method
System.out.println("\nThis point is: ");
myPointObject.Print();
// Call the point's distanceFromOrigin() method
distance = myPointObject.distanceFromOrigin();
System.out.println(" of distance from origin: " + distance);
// Change one of the data fields in the object
myPointObject.xCoordinate = -5.0;
}
} |
This specification for a new data type PointTester will need to go into a file called PointTester.java
Note:
Strings and String Literals
In Java, strings are objects (not built in types like int, double etc.)
The class definitions for String are all provided for you (you don't need to write a class String yourself)
You can make a String object using "double quotes" without using the new keyword. This type of object is called a String literal.
String scaryVoiceText = "\n\"Ha ha ha\", boomed the lecturer's terrifying voice."; |
You can concatenate strings across multiple lines using the "+" operator.
"the second part of the string"; |
To create a variable that can be a reference (name for) an object that isn't created yet...
|
Reference Types (and a note on Garbage Collection)
In Java, classes (and also arrays) are reference types.
Since classes and arrays are of variable size, (they are aggregates that can't be stored in a fixed amount of memory space) it is inconvenient for Java to try to treat them directly in the way it manipulates one of the built in types of fixed size (like an int or a double).
Instead, class and array types are manipulated indirectly through references. References are fixed size names for objects that exist in memory. In the case of classes, objects are called into existence using the new keyword or as literals (see above).
When all references to a particular object in memory are gone (i.e. there are no longer any names for a particular object that was new-ed) Java automatically deletes the object! This is called Garbage Collection.
C or C++ programmers must explicitly free() or delete() objects. This isn't necessary in Java.
The difference between reference and value types has important consequences for the way objects are passed to methods, on the use of the assignment operator "=" and on tests for equivalence using the "==" operator with objects...
Copying Objects
Point2D p1 = new Point2D(1.0, 1.0);
Point2D p2 = p1;
leaves us with a single Point2D object in memory that can be accessed using the references p1 or p2. Changes to p1 will affect the value of p2. Test this yourselves! (Its just like if you pay "Alan" $10, "Dr. Dorin" miraculously gets $10 too... the two names refer to the same person!")
If we really wanted p2 to be a reference to a complete copy of the object in memory referenced by p1...
Point2D p2 = (Point2D) p1.clone();
Note:
Comparing Objects
int a = 1, b = 2;
if (a == b) { System.out.println("a and b hold the same value"); }
but...
Point2D p1 = new Point2D(1.0, 1.0);
Point2D p2 = p1;
Point2D p3 = new Point2D(1.0, 1.0);
if (p1 == p2) { System.out.println("p1 and p2 are references to the same object"); }
if (p1.equals(p3)) { System.out.println("p1 and p3 are equivalent"); }
Note:
Type Conversions
Conversion between Primitive Types : was covered in Lecture 2a
Primitive Types and Reference Types : Java's interpretter will:
Reference Types and Reference Types : Java's interpretter will:
All Java classes are part of a class hierachy. Every class extends a superclass and inherits the fields and methods of this superclass (its parent in the class hierachy as discussed in lecture 1b). The root of the Java class hierachy is class Object. Every class in Java extends at least the class Object in some way and therefore inherits (or over-rides) Object's clone() and equals() methods and also its toString() method. |
All Strings are Objects. All Point2Ds are Objects.
Clearly not all Objects are Strings (some might be Point2Ds for example) and not all Objects are Point2Ds.
Java won't allow conversions between unrelated types so it will not allow conversions between Strings and Point2Ds, even if you try to cast a conversion.
Java will allow conversions from a class to its superclass (a widening conversion since the superclass is more broad than the subclass). So conversions from Point2D to Object are valid and conversions from String to Object are valid. No cast is required for widening conversions.
Java may allow conversions from a class to its subclass (a narrowing conversion since the subclass is less broad than the superclass) but a cast is required. The Java interpretter checks at runtime to make sure the conversion is valid. Only do this if you are sure that the subclass is actually an instance of the superclass.
E.g. This cast and narrowing conversion is OK because we know that myObject is actually a String.
String myString = (String) myObject; // cast conversion from Object to String is OK in this instance. |
Classes consist of data members (fields) and member functions (methods)
Objects are reference types. They are created using the new keyword or in the case of strings (and as we saw last lecture, arrays), using "literals". They are automatically garbage collected once there are no references to them.
Objects are copied using the clone() method and tested for equivalence using the equals() method if these methods have been properly defined for the class that the object is an instance of.
Widening conversions between reference types are fine. Narrowing conversions may be OK with a cast under some circumstances.