Objects, Instance variables and methods
Object References ** some of this is in the Constructor doc. Fix it so that there's no duplication
The new operator creates the object. It returns a reference to the object it created.
This reference is usually assigned to a variable of the appropriate type, like:
Point p1 = new Point(23, 94);
- the variable "p1" is a variable of type "Point", that is, it is a reference to a Point object. The variable is not the object, nor does it contain the object. It just points to the memory location of the object.
- You don't have to assign the reference to a variable, you can use it right away.
- You can also assign the reference to any superclass of the constructor
Assume thatpublic class SavingsAccount extends BankAccount { ...
then when you make a savings account, you can write:BankAccount account1 = new SavingsAccount("Sam Vimes", 2000.00);
Point p2 = p1;
This does not copy the point object, it just makes a second reference to the same object.
p1 and p2 are references (pointers) to the same object in memory.
If you typep1.x = 4;
, both p1 and p2 will have the x value set to 4.-
Cool trick: You can also use the methods of objects without assigning the object to something:
int areaOfRectangle = new Rectangle(100, 50).getArea();
This makes a rectangle of size 100x50, then calculates its area and assigns that to the int variable. - Also add this somewhere
import java.awt.Point; class MainClass{ public static void main(String[] args) { int n=100; Point p = new Point(4,4); meth1(p,n); System.out.println(p.x + " " + n); //p.x is changed, but n is not } static void meth1(Point p, int n){ p.x++; n++; } }
Deleting objects
To delete an object, set its refrence to null: p1 = null;
However, this object is not deleted yet, because there is still another reference to it. We made a reference called p2.
The object only gets deleted when there are no more references to it: p2 = null;
There, it's gone!
Instance methods
You're familiar with instance methods from using String and Scanner objects.
The String class does have (at least) one static method: String.format().
You don't have to create a String object to use this method.
You can't say String.toUpperCase()
,
but you have to make a String object first:
String s = new String("hello");
s = s.toUpperCase();
Likewise with Scanner, you have to always make a Scanner object and then do things with it:
Scanner scanner = new Scanner(System.in);
int x = scanner.nextInt();
Methods
The syntax for writing a method is:
modifiers return-value-type methodName (parameters) { statements in method body; }
modifiers : public, private, static, final, ... See List of modifiers
return-value-type : this is void (if nothing is being returned), int, double, char, ... or an object (i.e. a class name) String, Book, Point, AntiAircraftMissile
methodName : normally a verb. start with lowerCase.
(parameters) : you need the type and the name you'll be using in the method
Example:
static boolean checkout (Book b, Patron p) {
statements in method body;
}
This method probably does something like check out a book to a patron. It returns true/false to the calling program, depending on whether the operation was successful.
A better way to do this would be void checkout(Patron p) { ...}
and have this as an instance method in the Book class.
Thus a book could be checked out by writing book1.checkout(8532);
where 8532 is the patron number.
Overloading Methods
It is very common in Java to see two methods with the same name but different parameters. This is called overloading methods
Look at the section from the Polygon Class documentation. You'll see that there is only one way to add a point to a polygon: myPoly.addPoint(5, 5)
,
but there are many different methods to see if the polygon contains something.
This means that you don't have to make up a huge number of method names: containsIntPoint(), containsDoublePoint(), containsPoint(), containsRectangle(), ...
they can all just be called "contains()" because they are all doing the same thing.
Java automatically matches the parameter list with the function to make sure that it calls the correct one. (see below for more examples of this).
java.awt Class Polygon -- Method Summary | |
---|---|
void |
addPoint(int x,
int y)
Appends the specified coordinates to this Polygon . |
boolean |
contains(double x,
double y)
Tests if the specified coordinates are inside the boundary of the Shape . |
boolean |
contains(double x,
double y,
double w,
double h)
Tests if the interior of the Shape entirely contains
the specified rectangular area. |
boolean |
contains(int x,
int y)
Determines whether the specified coordinates are inside this Polygon . |
boolean |
contains(Point p)
Determines whether the specified Point is inside this
Polygon . |
boolean |
contains(Point2D p)
Tests if a specified Point2D is inside the boundary
of the Shape . |
boolean |
contains(Rectangle2D r)
Tests if the interior of the Shape entirely contains the
specified Rectangle2D . |
... | ... |
... | ... |
A weird example of overloading:
- In the example below you can easily see that adding two ints calls a different function from adding two doubles (the first one actually multiplies)
- BUT what happens if you call the add() funtion with one float and one int? It automatically casts the variables up to become doubles and uses the method for two doubles.
- and finally, in case you didn't already know, the order of the parameters is important. Thus, calling add() with an int then a char, is different from calling it with a char then an int.
public class Testing { public static void main (String[] args) { System.out.println( add(5, 6) ); //two ints System.out.println( add(5.0, 6.0) ); //two doubles System.out.println( add(5.0f, 6) ); //one float, one int //the order of the paramters is important too System.out.println( add(3, 'z') ); //int then char System.out.println( add('z', 3) ); //char then int } static double add(double a, double b) { return a+b; } static double add(int a, int b) { return a*b; } //this multiplies instead of adding static double add(int a, char c) { return a*2.0; } static double add(char c, int a) { return a*-2.0; } } //Output: // 30.0 // 11.0 // 11.0 // 6.0 // -6.0
Using "this"
Anytime you refer to an instance variable or method inside that class, you prefix it with the word "this".
This example is really not good! Rewrite it. (Feb 2018)
1 public class Rugby2 2 { 3 4 double radius = 27.0; 5 double length = 50.0; 6 7 void setSize(double r, double length) { 8 this.radius = r; //or just: radius = r; 9 this.length = length; 10 } 11 12 /* find the volume of any size rugby ball */ 13 double findVolume (double radius, double length) { 14 double vol = (4 * Math.PI /3 ) * radius * radius * length; 15 return vol; 16 } 17 18 /* find the volume of the rugby ball in this class */ 19 double findVolume() { 20 double vol = this.findVolume(this.radius, this.length); 21 return vol; 22 } 23 24 }
- Lines 4 and 5 define two instance variables. Any time you want to refer to these you should use this.
- Lines 8 and 9 are changing the values of these variables.
- Line 8 can be written in abbreviated form "radius = r;" since there is no other variable called radius. The only possibility is the instance radius (i.e. this.radius)
- Line 9 must have "this.length" to specify the instance variable and not the local variable in the parameter.
- Line 14 uses the local variables defined as parameters (radius and length).
- Line 21 uses the formula in the function at line 13. To call this function, you need to write "this.functionName(parameters)"
It calculates the volume based on the existing values for radius and length in the object. - Note that lines 14 and 15 can easily be combined (while still being easy to follow). Same with lines 20 and 21.
Private (i.e. Encapsulation)
Encapsulation means keeping the guts of your class hidden and inaccessible. It is very important.
Consider a car class. Assume that it has the following instance variables:
int odometer = 0;
float gas = 0.0f;
int speed = 0;
Date warrantyDate= new Date(2015, 2, 28); I know that Date() is deprecated, but Calendar is too complex
...
You don't want someone to be able to change the odometer or add a couple of years to the warranty. So, you make these fields private. This means that only methods in the Car class can access these fields. For other classes to access the odometer or warranty, they have to use get— and set— methods.
private int odometer = 0;
private float gas = 0.0f;
private int speed = 0;
private Date warrantyDate= new Date(2015, 2, 28);
public int getOdometer() {
return odometer;
}
public void setOdometer(int num) { X Do not make this function!
public void drive(int km) {
odometer += Math.abs(km); //prevent negative km from rolling back the odometer
//TODO: check gas tank ...
}
So you can see that you can read the odometer simply by calling getOdometer, but there is no way to set it. Also, everytime you drive, the odometer increases automatically.
In general, all instance variables should be private. Use getter and setter functions to access the private variables.
(Often some instance methods are set to private too.)