Now it's time to put together all that we've learned so far into a non-trivial (but just barely so) program.
public class Student { public void reportFeesOwing() { System.out.println("Owing: " + feesOwing); } public void PayFees() { feesOwing = 0; } private String name; private int age; private String courses; private double feesOwing = 5000.00; private boolean scholarship; } public class SecondProg { public static void main(String[] args) { Student s1 = new Student(); s1.reportFeesOwing(); s1.PayFees(); s1.reportFeesOwing(); System.out.println("This is my second program."); } }
What does this do?
Well, first of all the compiler sees
public class Student { public void reportFeesOwing() { System.out.println("Owing: " + feesOwing); } public void PayFees() { feesOwing = 0; } private String name; private int age; private String courses; private double feesOwing = 5000.00; private boolean scholarship; }
Remember that this is a recipe telling the compiler how to issue code to allocate memory, encode, and perform operations on our user defined type or class, Student. What the compiler does is to issue the appropriate instructions so that when we run the program the class definition information will be stored and can be referred to later in the execution of the program (when it comes time to actually allocate some memory for an object of this class.) So the compiler issues instructions so that when we run the program there will be some memory that looks like this:
The large box represents some memory of the machine (How much? It depends on the size of the methods and the number of member variables.) In the upper left corner we've written the address of this chunk of memory (this isn't actually stored in the chunk of memory! Memory addresses are given to the hardware along with the amount of memory that is needed, and the hardware reads that amount and gives it to the processor, roughly speaking)
However, the address in the top right corner, the address of the superclass, or containing class, is stored in this chunk of memory. Don't worry too much about the superclass; we'll talk about it very soon.
The code for the methods reportFeesOwing() and PayFees() (the method definitions) is also stored here as are the types of all the member variables.
Remember that this is the definition of the class; we do not yet have any memory allocated for the stuff that the class describes should be stored. (in this case, a String, an int, another String, a double, and a boolean value) The definition tells us how to allocate memory; it is the necessary information to create an object.
Allocating the memory for the stuff the class describes is is called instantiating, and the chunk of memory we get is called an object or instance of the class. The variables name, age, courses, feesOwing, and scholarship actually can store stuff once the object hs been instantiated; as a result they are called instance variables.
However we don't yet have any instance variables; we'll create some by instantiating an object next.
If we look at our program, we see that the first 'executable' line is
Student s1 = new Student();
This does a couple of things; in fact we could have written it as two statements:
Student s1; s1 = new Student();
The first line sets aside some memory for the reference to the chunk of memory that we're about to allocate (we can think about this as the address of the object's memory) ; from now on in the program we can refer to that chunk of memory by using the characters s1. The second line says 'allocate some memory according to the class definition that I gave you for Student, and then store the value of the reference to this chunk of memory in the memory location referred to by s1. So at the end of these two lines, we have the following additional memory allocated:
The smaller rectangular box on the left represents the memory that was allocated to store the value of s1. Note that the address (145) of this memory location is shown, but the value at that address is also an address! -- the address of the newly created object. Although we've spoken about references and addresses as if they are the same thing, they're not. But the concept is close enough that we'll continue to do so; you'll learn the details of the differences later.
Again the large rectangular box represents a chunk of memory, and the address of this chunk of memory is shown in the top left corner. The top right corner shows that the instantiated object keep some record of the class from which it came; this is actually a reference to the chunk of memory that contains the class definition.
Note although we see the method names reportFeesOwing() and PayFees(), the instructions generated by the compiler for these methods are actually located in the class definition; the object contains a kind of reference to the actual code. Finally, the storage for the instance variables is contained in this chunk. In reality, the values of the string variables are stored elsewhere, and only a reference to these values is stored in the object, but we won't worry too much about this fact right now.
So what does s1.reportFeesOwing(); do? Well, the value of textbfs1 refers is the address of the object, and reportFeesOwing() is a method of that object. We interpret this statement as saying 'run reportFeesOwing(), and use the values of the member variables in object s1'.
Can you describe what the remaining lines of the program do?verbatim How would you change the program to instantiate another object, called s2 for example? What would the memory look like? What would happen if we also added the line s2.reportFeesOwing(); ? What would be the difference in the output if we added this line before s1.PayFees();? After ?