University of Toronto - Summer 2001
Department of Computer Science
Week 4 - this example
By Prof. Bolintineanu

The Code

class Question {

	private String contents;     //contents of the question
	private Answer myAnswer;     //answer to the question

	//constructor -- notice it has the same name as the class,
	//and no return type
	public Question (String c) {
		contents = c;
	}

	//makes myAnswer become'ans' and sets ans's question to be this question
	//that is:  if I am the question for the given answer,
	//then the given answer is the answer to me
	public void setAnswer (Answer ans){
		myAnswer = ans;
		myAnswer.setQuestion(this);
	}
}

class Answer {

	private String contents;        //contents of the answer
	private Question myQuestion;    //question for this answer

	//constructor -- notice it has the same name as the class,
	//and no return type
	public Answer (String c) {
		contents = c;
	}

	//makes myQuestion become que
	public void setQuestion (Question que){
		myQuestion = que;
	}
}

public class Q&A {

	public static void main (String[] args) {

		Question q1 = new Question ("where are you?"); //diagram 1
		Answer a1 = new Answer("here");                //diagram 2
		q1.setAnswer(a1);                              //diagram 3
	}
}

Memory Model Diagrams

Diagram 1

Diagram 2

Diagram 3


Explanatory Notes to the Memory Model

Objects as Instance Variables?

Just as we can have integers, doubles, and Strings as instance variables, we can have objects from classes we define ourselves. Here, the Question class has an Answer object as an instance variable. And the Answer class has a Question object as an instance variable. This relationship can be reciprocal (i.e. class A has as instance variable an object of class B and class B has as instance variable an object of class A). But it doesn't have to be reciprocal (class A can have an instance variable an object of class B and class B can, for example, only have an instance variable of type int).

Memory Addresses

Note that the memory addresses are all unique 4-digit binary numbers. This is how you should represent memory addresses in the memory model -- as random 4-bit numbers, i.e. 4-digit integers consisting only of 0's and 1's. You have to do this on the quiz. [Note: Prof. Hunter will accept 3-digit numbers instead of 4-digit numbers, to save space.]

Diagrams and Program Execution

Diagram 1 traces line 1 of the main method just before it completes execution. That is, we can still see the method frame for the constructor of the Question class. Note the parameter (or argument-they mean the same thing) as a local variable inside the constructor frame. For more information on tracing a constructor call in the memory model, see the last page of "Memory Model" on the course website under Lecture 3.

Diagram 2 traces line 2 of the main method just before it completes execution. It traces, like Diagram 1, a call to a constructor method.

Diagram 3 traces a method call just before it completes execution. That is, it traces method setAnswer() of the Question class, which calls method setQuestion() of the Answer class.

Method setAnswer() of the Question class is called on the q1 object. (Remember, when we say a method meth() is called "on" the object obj, the method call looks like this: obj.meth(); . ) As a result, the number in the top right corner of the method frame is the memory address of q1. Important: whenever a method uses this, the keyword this refers to the object whose memory address is in the top right corner of the method frame. In this case, this is q1. Using this is the only way q1 can refer to itself and pass itself as a parameter to the setQuestion() method.

Method setQuestion() of the Answer class is called on the a1 object, which had been passed as a parameter to the setAnswer() method when setAnswer() was called from the main() method. The value of setQuestion()'s parameter is the memory address of q1. The object q1 was referred to as this in the method which called setQuestion().

Some memory addresses and method names in this diagram are coloured. The rationale behind the colouring scheme is this: to make the diagram clearer, every variable whose value is directly updated by a method has the colour of that method. So, the method setAnswer() directly updates the value of myAnswer in the q1 object, while the method setQuestion() directly updates the value of myQuestion in the a1 object. (You do not have to use any colouring scheme in your quiz!)

Note that the method frames are stacked so that the method which was called first is at the bottom and the method which was called last is at the top of the stack. The order in which we insert things into a stack is, after all, such that the latest inserted thing goes to the top.