An object is a container of named variables that lives in the heap.
The variables contained by an object are called the object's fields, attributes, member variables, or instance variables.
Each variable in an object can be referenced by its qualified name:
object.variable
Assume bank accounts are represented by objects containing one field of type float: balance.
Assume savings and checking are two objects representing my savings and checking accounts, respectively. Then:
savings.balance = the balance of my savings account
checking.balance = the balance of my checking account
Assume rational numbers are represented by objects containing two integer fields: numerator and denominator.
Assume rat1 represents the rational number 3/4 and rat2 represents 4/5. Then:
rat1.numerator = 3
rat1.denominator = 4
rat2.numerator = 4
rat2.denominator = 5
A class is a container of variable and method declarations.
Don't confuse variables and variable declarations.
Don't confuse methods and method declarations.
A class is a template for creating objects.
Here's what's going on in the following lines:
Rational rat1 = new Rational(3, 4);
Rational rat2 = new Rational(4, 5);
Account checking = new Account();
Account savings = new Account();
In the first two lines two objects are created in the heap. Each object contains two integer variables named numerator and denominator. References to these objects are stored in rat1 and rat2 respectively.
In the second two lines two more objects are created in the heap. Each object contains a variable named balance of type float.
We ask an object to execute a method with the following syntax:
Rational rat3 = rat1.mul(rat2);
savings.deposit(500);
We can consider rat1 and savings as implicit arguments to mul and deposit, respectively. In a non-object-oriented language these might be explicit arguments:
Rational rat3 = mul(rat1, rat2);
deposit(savings, 500);
The corresponding implicit parameter is always named this.
By using implicit arguments, instances (objects) of the same class can share methods.
The following sequence of instructions creates and initializes a new instance of CLASS:
new CLASS ; <...>
-> <a...> where a = reference to new object in heap
dup ; <a...> -> <a
a...>
invokespecial CLASS/<init>()V ;
<a a...> -> <a...>
The first instruction allocates a new object in the heap and pushes an address to this now object onto the operands stack.
The last instruction invokes the default constructor to initialize the fields of the newly allocated object. Unfortunately, it pops the stack. Therefore it is necessary to push a duplicate copy of the address on the stack. This is the function of the second instruction.
The Java statement:
new java.awt.Rectangle(50, 30); // creates rectangle with width 50 and height 30 at (0, 0)
is translated into Jasmin as:
new java/awt/Rectangle
dup
ldc 50
ldc 30
invokespecial java/awt/Rectangle/<init>(II)V
Continuing from the previous example, the following sequence of Jasmin instructions moves the (upper left corner of the) rectangle from (0, 0) to (10, 15):
dup
ldc 10
ldc 15
invokevirtual java/awt/Rectangle/setLocation(II)V
Continuing from the previous example, the following sequence of Jasmin instructions converts the rectangle into a string and stores it in locals[0]:
invokevirtual java/awt/Rectangle/toString()Ljava/lang/String;
astore 0
Continuing from the previous example, the following sequence of Jasmin instructions uses System.out.println to print the string stored in locals[0]:
getstatic java/lang/System/out Ljava/io/PrintStream;
aload 0
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
Here's the output produced:
java.awt.Rectangle[x=10,y=15,width=50,height=30]
Recall the Account class declared in Account.java.
Here's how a new Account instance is created and initialized:
new Account ; <...>
-> <a...> where a = ref to new Account
dup ; <a...> -> <a
a...>
invokespecial Account/<init>()V ; call constructor
Continuing from the previous example, the following sequence of Jasmin instructions deposits $50 into this account:
dup
ldc2_w 50.0
invokevirtual Account/deposit(D)V
Suppose the file Car.java contains the following class declaration:
public class Car extends Vehicle implements Carrier {
private double speed;
public void start() {
// etc.
}
}
A compiler that translated Java to Jasmin would translate Car.java into a file called Car.j that looked like this:
.class public Car ;
public class Car
.super Vehicle ; extends
Vehicle
.implements Carrier ; implements
Carrier
.field private speed D ; private
double speed;
; default constructor
.method public <init>()V
.limit stack 3
.limit locals 1
// call super()
aload_0 ; push this
invokespecial Vehicle()V
; init speed to 0.0
aload 0
ldc2_w 0.0
putfield Car/speed D
return
.end method
.method public start()V ;
.limit stack 4 ; start
requires a 4 word stack
.limit locals 2 ; start
requires space for 2 locals
; instruction go here
.end method
Assembling the file would create a file called Car.class.
Recall that one of the strengths of Object-Oriented Programming is the ability to define a class as an extension of an existing class. In this case the new or derived class inherits all of the fields and methods of the existing or base class.
Of course the inherited fields and methods may have been explicitly declared by the super class or inherited from its base class.
More formally, class A is a subclass of class B if:
A = B (i.e., a class is a subclass of itself)
A extends B
A extends C and C is a subclass of B
If A is a subclass of B, then we can also say that B is a superclass of A.
If A is a subclass of B, then A inherits all of the fields and methods of B.
If A is a subclass of B, then instances of A can be used in contexts where instances of B are expected. We say that instances of A can masquerade as instances of B.
For example:
B b = new A(); // an instance of A masquerading as an instance of B
How many subclasses does Employee have?
A .class file consists of seven tables:
1. version
magic number
minor version
major version
2. constant pool
count
constants
3. class
access flags (public, final, super,
interface, abstract)
class name
super class name
4. interfaces
count
interfaces implemented
5. fields
count
fields
6. methods
count
methods
7. attributes
count
attributes (for example bytecodes of
methods are here)
The JVM class loader:
Class.forName("MyClass.class")
locates the file MyClass.class and loads it into memory.
It validates the code in MyClass.class, returning an error if anything looks suspicious.
It creates a class object representing MyClass and stores it in the class area.