6.096 Quiz 1 Solutions

Summary

Question Mean Score StdDev Question Mean Score StdDev
1 7 5 9 2 6
2 4 6 10 3.2 5.8
3 7 4 11 7.1 4.6
4 1 5 12 7.4 4.5
5 1.3 5.6 13 2.3 5.4
6 7 3 14 5.3 5.6
7 1.7 6.2 15 6.5 4.4
8 4 5 Total 68.4 26.5

Question 1

Assume that the following classes have been defined.

If the following line of code is executed, what is printed?

  1. Nothing; the program won't compile because the classes have illegal syntax.
  2. Nothing; the program compiles, but execution causes an error.
  3. Just Basic method.
  4. Just Extended method.
  5. First Basic method
    then Extended method.
  6. First Extended method
    then Basic method.

The correct answer is d. The class Extended overrides Basic's printIt() method. Since method lookup is always outside-in, the new Extended's extended printIt() is found before its basic printIt(). Execution of the extended printIt() ends without calling the basic printIt(). (Only constructors automatically invoke superclass functionality.)

Question 2

If we have already declared

then the problem with the expression

is that

  1. it is redundant to compare a boolean to true.
  2. the underlined item changes the value of isHappy.
  3. isHappy can't be assigned true; it's already false.
  4. the underlined item is not an expression; it's a statement.
  5. isHappy isn't properly declared.
  6. true isn't properly declared.

The correct answer is a. It is redundant to compare a boolean to true; isHappy is true, or it isn't, all by itself. The expression isHappy has the same type and value as isHappy = true.

As to the other answers: The == operator doesn't change the value of isHappy; Java assignment uses a single =. There's nothing wrong with the declaration of isHappy, and true is a Java (boolean) literal (and a keyword).

Question 3

If we are inside the act method of a NodeBehavior with parameters ins and outs -- that is, inside a method with the declaration

-- and ChannelInputStream has a readObject method specified as

then the type of the expression ins[3].readObject() is

  1. 3.
  2. ChannelEmptyException.
  3. ChannelInputStream.
  4. Object.
  5. null.
  6. void.

The correct answer is d. ins is of type ChannelInputStream[] (array of ChannelInputStreams). ins[3] refers to the 4th ChannelInputStream in ins. (Remember, Java arrays start at 0.) So the type of ins[3] is ChannelInputStream. Each ChannelInputStream has a readObject() method. The type returned by this method is Object; you can tell that from its declaration. The type of a method invocation expression is the return type of the method. So ins[3].readObject() is an expression with type Object.

Question 4

Which of the following could be a legal Java constructor method for class Classic? You may assume that Classic defines any necessary methods or fields.

  1. public Classic {
        super();
    }
  2. public void Classic () {
    }
  3. Classic (int i) {
        this.number = i;
        super();
    }
  4. Classic () {
    }
  5. public Classic (int i) {
        this.number = i;
        return i;
    }
  6. public Classic () {
        return new Classic();
    }

The correct answer is d. Answer a is missing the parentheses after the constructor name. Answer b has a return type; constructors don't. Answer c calls super(); in its second line. If super(); is present, it must be the first line of the constructor.  Answer e has a return, which constructors don't. Answer f has the same problem: a return.  Also, you can't invoke a constructor (new Classic()) inside that constructor (Classic()).

Question 5

Assume that the following class has been defined:

Which of the following statements is true?

  1. new Test() has type Object.
  2. Line 4 is nonsensical (that is, not legitimate Java).
  3. The setName method is redundant because you can always use the name field directly.
  4. If foo is an appropriately declared label and we assign foo = new Test( "foo" ), then foo.getName has the same value as foo.
  5. If foo is an appropriately declared label and we assign foo = new Test( "foo" ), then foo.setName( "bar" ) does not change the value bound to the label foo.
  6. If foo is an appropriately declared label and we assign foo = new Test( "foo" ), then foo.name is never legal Java.}

The correct answer is e.

Answer a is incorrect because new Test() is not a legal expression, given this class definition. class Test has an explicitly defined constructor, and that constructor requires a parameter.

Answer b is simply wrong: Line 4 is perfectly legitimate Java and a common way of initializing a field.

Answer c misses the fact that setName is public, while name is private. This means that objects other than Tests can't use name directly.

Answer d would mean that a Test and a String had the same value; since neither is a subclass of the other, this isn't possible.

Answer e is correct: foo's binding doesn't change, though the object it is bound to (the thing it labels) has one of its labels change.

Answer f is false because foo.name is legal inside the Test class.

Question 6

Assume that the following class has been defined:

(This definition is identical to that in Question 5.)

Further, assume that the following lines of code are executed in order.

  1. Test firstTest = new Test( "who" );
  2. Test secondTest, thirdTest = firstTest;
  3. new Test ( "what " );
  4. firstTest = secondTest;
  5. secondTest = new Test( "who " );
  6. Test fourthTest = firstTest;

Which of the following statements is true?

  1. At the end of this sequence (that is, after line 6), secondTest is null.
  2. The name fourthTest never has the value null.
  3. Line 4 changes the value of thirdTest.
  4. This sequence of numbered lines creates exactly two Objects.
  5. The object labeled by firstTest immediately after line 1 is the same as the object labeled by secondTest immediately after line 5.
  6. The value of the label firstTest immediately after line 4 is the same as the value of the label by secondTest immediately after line 2.

The correct answer is f.

Answer a is false: secondTest is used to label a new Test object on line 5, and nothing on line 6 changes that.

Answer b is incorrect because fourthTest is assigned the value of firstTest on line 6. On line 4, firstTest gets the value of secondTest. But secondTest has never been given a value, so it is not stuck on anything, i.e., it is null. This means that line 4 makes firstTest null, and line 6 makes fourthTest null.

Line 4 has nothing to do with thirdTest.

There are three objects created in this sequence, one by each invocation of new Test(...) -- on lines 1, 3, and 5.

The object labeled by firstTest after line 1 is a new Test object. The object labeled by secondTest after line 5 is another new Test object. Each invocation of new Test( ... ) creates a brand new, never-before-seen instance of Test.

After line 2, the value of secondTest does not change until line 5. Line 4 sticks the firstTest label onto the object currently referred to by secondTest, i.e., the value that secondTest was assigned (or not assigned) on line 2.

Question 7

Assume that the following interface has been defined:

Which of the following is not a legitimate definition?

  1. public class Chuckler implements Laughable {

        public String laugh ( String fury, int m ) {
            String sound = "";
            int i = 0;
            while ( i < m ) {
                sound = sound + fury;
                i = i +1;
            }
            return sound;
        }

    }
  2. public class Chortler implements Laughable {

        public String laugh ( String sound, int n ) {
            return sound + n;
        }

    }
  3. public class Santa {

        public String laugh () {
            return "Hohohohoho";
        }

    }
  4. class MultiLaugher implements Laughable {

        public String laugh ( String sound, int n ) {
            if ( n == 1 ) {
                return "teeheehee";
            } else if ( n == 2) {
                return "guffaw";
            } else if ( n == -1.5 ) {
                return "snicker";
            } else {
                return "ker-choo";
            }
        }

    }
  5. public class Giggler implements Laughable {

        public void laugh ( String sound, int n ) {
            System.out.println( "hahahaha");
        }

    }
  6. public class Cackler implements Laughable, Runnable {

        private spirit;

        public String laugh ( String sound, int n) {
            this.spirit = new Thread( this );
            this.spirit.start();
            return sound;
        }

        public void run () {
            while (true) {
                System.out.println("Ahhahahahah");
            }
        }

    }

The correct answer is e. In order to implement Laughable, a class must have a method that is called laugh, takes a String and an int (in that order, but with any names), and returns a String.

Chuckler may be rather roundabout, but it successfully implements the Laughable interface.

Chortler does too. It uses the "stupid + trick" to concatenate Strings.

Santa's laugh method doesn't take the right parameters, but that's OK: Santa doesn't promise to implement Laughable.

Multilaugher implements Laughable successfully: its laugh method takes a String and an int and returns a String.

Giggler doesn't implement Laughable: its laugh method returns void, violating the interface specification.

Cackler successfully implements both laugh and run. It is a legitimate definition.

Question 8

Assume that the following declarations apply:

Which of the following Java fragments has the value true ?

  1. isSunny;
  2. !0
  3. i + 3 <= i
  4. (isSunny && isSunny) || isSunny
  5. if (i == 0 ){
        return true;
    }
  6. (int) i

The correct answer is d. Answers a and e are statements, not expressions; statements do not have values. Answer b is a type error: you can't use logical negation (!) with an int, only with a boolean. Answer c is of type boolean, but its value is false. (Adding 3 to i will make it larger, not smaller, than itself.) Answer f is an expression with type int, not boolean: it is a cast expression. Only answer d has type boolean and value true.

Question 9

Consider the following class definition:

Which of the following statements is true?

  1. The line declaring myNum is not legitimate Java.
  2. The line declaring the String field is not legitimate Java.
  3. The line declaring anotherNum and lastNumDefined is not legitimate Java.
  4. None of the declarations is legitimate Java.
  5. Exactly one of the declarations is legitimate Java.
  6. All of the declarations are legitimate Java.

The correct answer is b. myNum's definition is legitimate, even though it refers to lastNumDefined, which isn't defined until later. All fields and methods (of the same class) are visible to one another. anotherNum and lastNumDefined are also legitimate; this is the two-names-for-one-definition form. But the String field doesn't have a name, so the declaration is not valid.

Question 10

Which of the following statements is true?

  1. The reference to this.name in Fred's method getName is illegal.
  2. The reference to this.name in Fred's method otherMethod is illegal.
  3. The reference to this.name in Barney's method barneyMethod is a legal reference to "Fred".
  4. The reference to fred.name in Barney's method barneyMethod is a legal reference to "Fred".
  5. The reference to Fred.name in Barney's method barneyMethod is a legal reference to "Fred".
  6. All of the references to name in Barney's method barneyMethod are illegal.

The correct answer is f. The references to this.name in Fred's class are both legal. this.name refers to Fred's name field, regardless of the names of parameters or local variables. And within the Fred class, it doesn't matter if name has been defined to be private.

The references to name in Barney's methods are not legal, though. this.name would refer to Barney's name field; but Barney doesn't have one. fred.name refers to the Fred object bound to the local variable fred, but Fred objects' name fields are private. Fred.name would refer to the static field of the Fred class, but name is not a static field.

Question 11

Consider the following code:

Some of these lines are commented out. Others may be partially commented out, or not commented out at all. For example, 0 refers to a line that is not a comment.

Which one of the following sets of numbers includes only lines that are fully commented out?

  1. 1,2,3
  2. 5,6,7
  3. 8,9,10
  4. 1,3,5
  5. 2,4,6
  6. 3,6,9

The correct answer is b. Line 1 is fully commented out . Line 2 is not: // comments only comment out the remainder of the line that they are on. Line 3 is partially commented out: Yet another is not commented out, but possible comment is. Line 4 is again fully commented out.

/* comments, unlike // comments, persist for multiple lines. In fact, they continue until the first */, regardless of //s. However, they don't nest: no matter how many /*s you have, the first */ ends the comment. So lines 5-9 are commented out (fully), but line 10 is not.

Question 12

Consider the following code:

The return statement in the returnNumber method is missing its return expression. Which one of the following is not a legitimate expression to be returned by returnNumber? (Cross out each of the choices that could legitimately be used to replace something in the return statement.)

  1. 42
  2. this.myNumber
  3. aNumber
  4. this.magicNumber()
  5. anotherNumber
  6. Math.round( 3.1f )

The correct answer is e. The only requirement on somethingis that it must be a legitimate expression with type int. 42 is. this.myNumber refers to the field, which has type int. aNumber refers to the parameter, which has type int. this.magicNumber() invokes a method, which has return type int.And Math.round( float ) returns int. But anotherNumber is a parameter to magicNumber(), not to returnNumber() -- its name is not accessible within returnNumber.

Question 13

Consider the following class definition:

Which one of the following statements is false? (Cross out the true statements.)

  1. A Thread is what allows this object to be self-animating, i.e., to perform actions on its own.
  2. This code would do the same thing if the field spirit were eliminated and the two lines in the body of the constructor were replaced with
            new Thread( this ).start();
  3. Calling new AnimateObject(), without doing anything else, will cause the standard output (e.g., the Java console) to fill up with I'm here! lines.
  4. It is only possible to call new Thread( this ) because AnimateObject implements Runnable.
  5. this.spirit.start() causes execution of the object's run method.
  6. Because the run method contains an infinite loop, the call to this.spirit.start() never returns.

The correct answer is f.

A is self-explanatory and true.

B is also true. If this change were made, AnimateObjects would not have access to their Threads outside of their constructors, but the code would still behave in the same way.

C is true because the run method will run away!

D is true because the Thread constructor requires that its argument be a Runnable.

E is true because that is what a Thread's start() method does.

F is false because the call to start() returns no matter what. It is the new Thread (this.spirit) that gets caught up in the infinite run loop.

Question 14

Assume the following definitions:

Which of the following statements causes a type casting exception? You may assume that each line is independent, i.e., they are not executed one after the other.

  1. l = (double) i;
  2. d = (double) l;
  3. d = (long) i;
  4. l = i;
  5. l = (int) d;
  6. l = (int) l;

The correct answer is a. Remember: byte to short to int to long to float to double. This direction can be done automagically, but the other way requires explicit intervention.

A is invalid because after i is cast to double, it is too wide to be automatically cast to long.

B is valid: long to double explicitly is OK, then double to double implicitly is OK.

C is valid: into to long explicitly is OK, then long to double implicitly.

D involves only a (legal) implicit widening from int to long.

E involves an explicit narrowing of a double to an int. This is dangerous (and possibly lossy), but perfectly legitimate Java. Once we have an int -- and the type of the expression (int) d is int -- then widening to a long is no problem. (Java doesn't care that the int used to be a double.)

Similarly, the narrowing cast from long to int in F is dangerous, but legal; the widening cast back to long won't restore lost information, but it is still legitimate Java.

Question 15

Assume the following definitions:

    public class BaseClass implements Laughable {
      public String laugh (String sound, int n) {
          return sound;
      }
    }
    public class Polytipic extends BaseClass implements Runnable {
      private Thread spirit;
      public Polytipic() {
          this.spirit = new Thread( this );
          this.spirit.start();
      }
      public void run() {}
    }

Now, assume that we declare

Which of the following could not be used as a replacement for SomeType in this declaration? (Cross out the choices that would be legitimate types for SomeType.)

  1. Polytipic
  2. BaseClass
  3. Runnable
  4. Laughable
  5. Object
  6. Thread

The correct answer is f. Any type that is a legitimate type for Polytipic can be used as a substitute for SomeType. Polytipic extends BaseClass and implements Runnable, so a PolyTypic is a Polytypic, a BaseClass, and a Runnable. Since BaseClass implements Laughable, every BaseClass instance is also a Laughable; a Polytypic is a BaseClass, so it's a Laughable. Since BaseClass doesn't explicitly extend another class, it implicitly extends Object, so a Polytypic is an Object, too. (Everything that isn't an int, short, byte, long, char, double, float, boolean, or void is an Object.)

But a Polytypic isn't a Thrread; it just has one.



This course is a part of Lynn Andrea Stein's Rethinking CS101 project at the MIT AI Lab and the Department of Electrical Engineering and Computer Science at the Massachusetts Institute of Technology.