6.170 / Spring 2001 / Lecture 3 Card Answers

Handout L3-QA

Contents:


Compile-time vs. Run-time Types

Question: Explain the difference between compile-time type and run-time type.
Answer: Variables and other Java source code expressions have a compile-time type, which the compiler uses to determine legality of certain expressions (such as field accesses or method calls). Objects that are created during the execution of a Java program have a run-time type, which the Java virtual machine uses to determine what method implementations should be called and to check the legality of casts.

This material is covered in the book as well as in lecture. See section 2.4 of Program Development in Java, "Type Checking," and please note that the book refers to "compile-time type" as "apparent type" and "run-time type" as "actual type".

Here is an example to help distinguish between compile-time types and run-time types:

import java.util.Vector;
import java.util.List;
...
     Vector vec = new Vector();
     List list = vec;
     Object obj = list;
...
In the above code, there is only one instance of an object; the object created by the expression new Vector(). Thus, it has a run-time type of Vector; expressions of the form "new X(...)" will always return an instance of X. There are three variables: vec, list, and obj. They all refer to the same object, but each has a different compile-time type ( Vector, List, and Object, respectively).

The compiler will allow calls like vec.lastElement(), list.clear(), and obj.toString(), because those are all methods associated with the compile-time types for each of those variables. The compiler will also statically ensure that the Vector class actually implements all of those methods, because the Vector class subclasses Object and implements List. The compiler will not allow calls like obj.clear() or list.lastElement(), because those methods are not declared by the compile-time types associated with those variables, and therefore are not guaranteed to be implemented by every object that the variables might point to.


Casting

Question: Could you give more detail on the usefulness + pertinent functionality of casts?
Answer: Casts are used in Java to allow code to view an object as a more restricted type than what is immediately apparent at compile-time (i.e., as a subtype of the compile-time type). In the above example, we noted that calls like obj.clear() and list.lastElement() were not legal. Not only that, but assignments such as
    Vector vec2 = obj;
are also not legal, because the compiler cannot determine that the object referred to by the obj variable is a Vector. However, implementors can reason about the code that they write, and ensure that obj will always point to an instance of a Vector. If the implementor is sure of this, then she can write the code:
    Vector vec2 = (Vector) obj;
This inserts code to check that the object referred to by obj is indeed a Vector, and thus guarantees that if the assignment happens, it is safe to use vec2 as a Vector.

Why do we need casts? To allow objects to be passed around in a generic fashion while preserving type safety. A good example of this is the Vector class itself; it holds a sequence of objects, but it doesn't care about the types of the objects that it holds. Therefore, to allow code to make one vector containing Integers and another vector of Strings, the designers of Java established a type-hierarchy where every class extends the Object class. Thus the Vector class only requires users to pass it variables of type Object as arguments, and so one only needs to implement a single Vector class (as opposed to a VectorOfString class and a VectorOfInteger class). This genericity comes at a price though; the Vector class also only guarantees that it will return instances of Object when queried; it is up to the implementor to keep track of what types of objects are put into the vectors so that they can be casted successfully to the appropriate type upon retrieval.


Object Initialization

Question: Could one use "Transaction(amount, new Date());" instead of "this(amount, new Date());" in slide 6? Why or why not?
Answer: No, one must use the this(...) syntax to delegate initialization to another constructor in the same class. The designers of Java decided that it was best to overload the this keyword for use in initialization delegation as well as disambiguation of field references.

There are a variety of reasons for this decision; one simple one (that may surprise you) is that it is legal in Java to write the following code:

class Transaction {
    int amount; Date date;
    public Transaction(int amount, Date date) {
        this.amount = amount;
        this.date = date;
    }
    ...
    // the "void" keyword here is a return type,
    // making this a method declaration, not a constructor.
    public void Transaction(int amount, Date date) {
        ...
    }
}
(Of course, just because you can do something does not mean that you should. The above code tends to reflect bad style, and some compilers, such as jikes, will even issue a warning upon encountering such code. )

Question: What is super(name) in slide 9 ?
Answer: This is the counterpart to using "this(...);" to delegate initialization to another constructor in the same class. The statement "super(...);" delegates initialization as well, but instead of delegating it to a constructor in the same class, it delegates initialization to a constructor in the superclass.

In this case, the OverdraftAccount(String, int) constructor first delegates initialization to the Account(String) constructor, and then runs its own initialization code.

See your Java text for more details.

Question: How come transactions Vector was initialized and name wasn't?
Answer: Both are initialized. The code for initializing transactions is located outside of the constructor, which means that the creation of a new Vector and assignment to the transactions field is implicitly done for each new instance of an Account, before the constructor initialization code is called. The code for initializing name is located within the constructor, which means that it is called during the execution of the constructor initialization code.

Note that the code given is functionally equivalent to:

class Account {
    String name;
    Vector transactions;
    int balance;
    Account(String name) {
        this.transactions = new Vector();
        this.balance = 0;
        this.name = name;
    }
    ...
}
It is merely a matter of stylistic preference to choose one over the other; the style presented in lecture is convenient at times but can also lead to subtle bugs if used without care.


Method Dispatch

Question: How do we know which version of check(Transaction) was used?
Answer: When a method invokes a method on an object, it asks the receiver object to determine the appropriate code to call (this is known as dispatch). This process occurs when one object makes a call on another object, and it also occurs when the code for an object makes a call upon itself!

Thus, you can predict which version of check will be called based on your knowledge of what will be the run-time type of the receiver object. In the example given in lecture, a call to post on an object whose run-time type is OverdraftAccount will cause the OverdraftAccount.check(Transaction) method to be called, while a call to post on an object whose run-time type is Account will cause the Account.check(Transaction) method to be called. Note that in both cases, it is the code for post in the Account class that is called!

You should read section 2.5 of the text, "Dispatching," for more information. If the material is still unclear after you've read the text a few times, talk to your TA.


Lab Session Answers

Question: Could answers to the labs be posted on the web page? I went, but didn't get through all of it.
Answer: The staff may do this in the future. In the meantime, you should try to work through the problems on your own. You can also see an LA, or your TA, to resolve any confusions you have about the material covered.
Back to Index Card Answers.
Back to the 6.170 home page.
For problems or questions regarding this page, contact: 6.170-webmaster@mit.edu.
$Id: lec03-qa.html,v 1.31 2001/02/15 01:56:06 mernst Exp $