Answers to Questions


(a), (b), (c), and (e)

Only local variables need to be explicitly initialized before use. Fields are assigned a default value if not explicitly initialized.


(a), (d), and (e)

When the >> operator shifts bits to the right, it fills the new bits on the left with the bit value of the left-most bit of the original bit pattern. When the >>> operator shifts bits to the right, it always fills the new bits on the left with a bit value of 0. Thus, the >> and the >>> operators perform the same operation when the left-most bit of the original bit pattern has a bit value of 0. This occurs whenever the original value is non-negative.

The result of (-1 >> 1) is ?1. A bit pattern consisting of all 1s (i.e., integer -1) will not change after being shifted by the >> operator.

The result of (-1 >>> 1) is 2147483647 which is 231 ? 1. Shifting a bit pattern of all 1s one bit to the right using the >>> operator will yield a bit pattern of all 1s, except for the left-most bit which will be 0. This gives the non-negative value 2147483647, which is the maximum value of type int.

The >>> operator will shift 0s into the bit pattern from the left, thus giving the leftmost bit a value of 0. Since a value of 0 in the left-most bit signifies a non-negative value, the >>> operator is guaranteed to return a non-negative number if a shift has actually occurred.



A try block must be followed by at least one catch or finally block. No catch blocks can follow a finally block. Methods need not declare that they can throw Runtime Exceptions, as these are unchecked exceptions.



Giving parameters (2, 3) to the method substring() constructs a string consisting of the characters between positions 2 and 3 of the original string. The positions are indexed in the following manner: position 0 is immediately before the first character of the string, position 1 is between the first and the second character, position 2 is between the second and the third character, and so on.



A Thread object executes the run() method of a Runnable object on a separate thread when started. A Runnable object can be given when constructing a Thread object. If no Runnable object is supplied, the Thread object (which implements the Runnable interface) will execute its own run() method. A thread is initiated using the start() method of the Thread object.



The loop prints out the values 12, 9, 6, and 3 before terminating.



The fact that a field is static does not mean that it is not accessible from non-static methods and constructors. All fields are assigned a default value if no initializer is supplied. Local variables must be explicitly initialized before use.



The ^ operator will perform an XOR operation on the bit patterns 1001 and 0010, resulting in the bit pattern 1011, which will be written out in decimal form as 11.



All the "hello" literals denote the same String object. Any String object created using the new operator will be a distinct new object.


(d) and (e)

The main() method must be public and static, and take an array of String objects as parameter. It does not return a value and, therefore, should be declared void. The public and static modifiers must precede the keyword void. The (b) and (c) declarations will fail to compile due to error in the syntax of the method declaration.

Declaration (a) will compile, but it does not meet the criteria of a main() method to start the execution of an application. Declaration (d) meets the criteria although the method is declared final, which is redundant since the method is static. It also uses a different parameter name, but it is none the less also a valid main() method. Declaration (e) is the canonical form of the main() method.



Calls to methods suspend(), sleep(), and wait() do not stop a thread. They only cause a thread to move out of its running state. A thread will terminate when the execution of the run() method has completed.



The Map interface provides operations that map keys to values.



The >>> operator clears the sign bit, so for negative values i >>> 1 is not equivalent to i/2.



An object of the class Extension is created. The first thing the constructor of Extension does is invoke the constructor of Base, using an implicit super() call. All calls to the method void add(int) are dynamically bound to the add() method in the Extension class, since the actual object is of type Extension. Therefore, this method is called by the constructor of Base, the constructor of Extension and the bogo() method with the parameters 1, 2, and 8, respectively. The instance field i changes value accordingly: 2, 6, and 22. The final value of 22 is printed.


(a) and (b)

The native modifier can be specified in the same position as accessibility modifiers in method declarations. Thus, the order of tokens in (a) and (b) is correct. The (c) declaration is rejected since the native modifier is not allowed after the declaration of the return type. Declaration (d) is rejected since it tries to declare an abstract method within a non-abstract class. The (e) declaration is rejected because native method declarations, just like abstract method declarations, cannot have an implementation since this is defined elsewhere.



TreeMap and HashSet do not maintain an ordered sequence of objects. Vector and ArrayList require shifting of objects on insertion and deletion, while LinkedList does not. When objects are frequently inserted and deleted from the middle of the sequence, LinkedList gives the best performance.


(a) and (d)

Field b of the outer class is not shadowed by any local or inner class variables, therefore, (a) will work. Using this.a will access the field a in the inner class. Using this.b will result in a compilation error since there is no field b in the inner class. Using Q4a39.this.a will successfully access the field of the outer class. The statement c = c will only reassign the current value of the local variable c to itself.



At (1), a new String object is constructed by concatenating the string "bye" in the String object denoted by b and the string "!". After line (2), d and b are aliases. After line (3), b and a are aliases, but d still denotes the String object with "bye" from line (0). After line (4), d and a are aliases. Reference d no longer denotes the String object created in line (0). This String object has no references to it and is, therefore, a candidate for garbage collection.



String objects are immutable. None of the methods of the String class modify a String object. Methods toUpperCase() and replace() in the String class will return a new String object that contains the modified string. However, StringBuffer objects are mutable.



Statement (a) will work just fine, and (b), (d), and (e) will cause compilation errors. Statements (b) and (e) will cause compilation errors since they attempt to assign an incompatible type to the reference. Statement (d) will cause compilation errors since a cast from B to C is invalid. Being an instance of B excludes the possibility of being an instance of C. Statement (c) will compile, but will throw a runtime exception since the object that is cast to B is not an instance of B.


(a), (d), and (e)

String is a name of a class in the java.lang package, not a keyword. Java has a keyword null, but not NULL.



The desired accessibility is package accessibility, which is the default accessibility for members that have no accessibility modifier. The keyword package is not an accessibility modifier and cannot be used in this context.


(b) and (e)

For the expression tab[3][2] to access a valid element of a two-dimensional array, the array must have at least four rows and the fourth row must have at least three elements. Fragment (a) produces a 2 x 3 array. Fragment (c) tries to initialize a two-dimensional array as an one-dimensional array. Fragment (d) tries to specify array dimensions in the type of the array reference declaration.



The expression arr.length will evaluate to 4. The expression arr[1] will access the element { { "1", "2" }, { "1", null, "3" } }, and arr[1][2] will try to access the third sub-element of this element. This produces an ArrayIndexOutOfBoundsException, since the element has only two sub-elements.


(c) and (d)

String objects can have identical sequences of characters. The == operator, when used on String object references, will just compare the references and will only return true when both references denote the same object (i.e., are aliases). The equals() method will return true whenever the contents of the String objects are identical. An array of char and a String are two totally different types and cannot be compared using the equals() method of the String class.


(b) and (c)

Statement (d) is false since an object of B can be created using the implicit default constructor of the class. B has an implicit default constructor since no constructor has explicitly been defined. Statement (e) is false since the second constructor of C will call the first constructor of C.


(b) and (d)

The retainAll(), removeAll(), and addAll() methods do not return a new collection object, but instead modify the collection object they were called upon. The collection object given as an argument is not affected. The containsAll() does not modify either of the collection objects.


(b), (c), and (e)

An instance of the class Baz is also an instance of the class Foo since the class Baz extends the class Foo. A Baz has a Bar since instances of the class Baz contain an instance of the class Bar by reference. A Foo has a Baz since instances of the class Foo contain an instance of the class Baz by reference. Since a Foo has a Baz which has a Bar, a Foo has a Bar.


(b) and (e)

Unlike local variables, all fields are initialized with default initial values. All numeric fields are initialized to zero, boolean fields to false, char fields to '\u0000', and all reference fields to null.


(c) and (d)

Very little is guaranteed about the behavior of the garbage collection and finalization mechanisms. The (c) and (d) statements are two of the things that are guaranteed.



The main() method in (b) will always generate and catch an ArrayIndexOutOfBoundsException, since args.length is an illegal index in the args array. The main() method in (c) will always throw an ArrayIndexOutOfBoundsException since it is also uses args.length as an index, but this exception is never caught. The main() method in (d) will fail to print the argument if only one program argument is supplied. The main() method in (e) will generate an uncaught ArrayIndexOutOfBoundsException if no program arguments are specified.


(a), (b), and (c)

Set and List both extend Collection. A map is not a collection and Map does not extend Collection. Set does not have any new methods other than those defined in Collection. List defines additional methods to the ones in Collection.



The type short defines 16-bit signed values in the range from ?215 to 215?1, inclusive.


Filled in:




The important thing to remember is that if an object is an instance of a class, then it is also an instance of all the superclasses of this class.



The expression (int) d evaluates to ?2. The expression Math.ceil(d) evaluates to ?2.0, giving the value ?2 when converted to int. The expression Math.abs(d) evaluates to 2.9, giving the value 2 when converted to int.



Method g() modifies the field a. Method g() modifies the parameter b, not the field b, since the parameter declaration shadows the field. Variables are passed by value, so the change of value in parameter b is confined to the method g(). Method g() modifies the array whose reference value is passed as a parameter. Change to the first element is visible after return from the method g().


(a), (c), and (e)

The equals() method ignores the ordering of a and b when determining if two objects are equivalent. The hashCode() implementation must, therefore, also ignore the ordering of a and b when calculating the hash value, that is, the implementation must return the same value even after the values of a and b are swapped.


(c) and (d)

The variable j is only decremented if assertions are enabled. The assertion never fails, since the loop condition ensures that the loop body is only executed as long as i<j is true. With assertions enabled, each iteration decrements j by 1. The last number printed is 20 if assertions are disabled at runtime, and the last number printed is 4 if assertions are enabled at runtime.


(b) and (c)

These names have overloaded methods that allow optional timeout values as parameters.


(a), (b), and (d)

Both $ and _ are allowed as characters in identifiers. Character @ is not allowed in identifiers. All characters considered letters in the Unicode character set are allowed. The first character of an identifier cannot be a digit.



The program will fail to compile since the label l2 cannot precede the declaration int j = 0. For a label to be associated with a loop, it must immediately precede the loop construct.



Classes cannot extend interfaces, they must implement them. Interfaces can extend other interfaces, but cannot implement them. A class must be declared abstract if it does not provide an implementation for one of its methods. Methods declared in interfaces are implicitly public and abstract. Classes that implement these methods must explicitly declare their implementations public.


(a) and (e)

The notify() and notifyAll() methods are declared in the class Object. Since all other classes extend Object, these methods are also available in instances of all other classes, including Thread. The method notify() is not synchronized, but will throw an IllegalMonitorStateException if the current thread is not the owner of the object lock.


(a) and (c)

Accessing fields of the outer instance using only the variable name works within the inner instance as long as the variable is not shadowed. Fields need not be declared final in order to be accessible within the inner instance.



The code will fail to compile because the literal 4.3 has the type double. Assignment of a double value to a float variable without an explicit cast is not allowed. The code would compile and write 0 to standard output when run, if the literal 4.3 was replaced with 4.3F.


(b) and (e)

The && and || operators exhibit short-circuit behavior. The first operand of the ternary operator (? :) is always evaluated. Based on the result of this evaluation, either the second or the third operand is evaluated.



No labels are mandatory (including the default label) and can be placed in any order within the switch body. The keyword continue may occur within the body of a switch statement as long as it pertains to a loop. Any constant non-long integral value can be used for case labels as long as the type is compatible with the expression in the switch expression.


(b) and (c)

The main() method must be declared static. It does not return a value and is, therefore, declared as void. It's accessibility modifier must be public. It has an array of String as parameter. Additionally it can be declared final, but that is not part of the requirement.


(a), (b), and (e)

Expressions (a), (b), and (e) all call the method hashCode() on valid objects. (c) is an illegal expression, as methods cannot be called on primitive values. The call in (d) to the equals() method requires an object as argument.



The method returns true if and only if assertions are enabled at runtime. It will only return false if assertions are disabled.


(c) and (d)

(d) shows how the static method parseInt() of the wrapper class java.lang.Integer can be used to parse an integer from its string representation. It is also possible to first construct an Integer object based on the string representation and then extract the int value, using the intValue() method, as shown in (c).


Filled in:


Overridden method implementations are accessed using the super keyword. Statements like print(), Base.print(), and Base.this.print() will not work.


(c) and (d)

Executing synchronized code does not guard against executing non-synchronized code concurrently.



Strings are immutable, therefore, the concat() method has no effect on the original String object. The string on which the trim() method is called consists of 8 characters, where the first and the two last characters are spaces (" hello "). The trim() method returns a new String object where the white space characters at each end have been removed. This leaves the 5 characters of the word "hello".


(a) and (b)

If a thread is executing method b() on an object, then it is guaranteed that no other thread executes methods a() and b() concurrently. Therefore, the invocation counters i and j will never show more than one concurrent invocation. Two threads can concurrently be executing methods b() and c(). Therefore, the invocation counter k can easily show more than one concurrent invocation.


(a), (b), and (e)

Widening conversion allows conversions (a) and (b) to be done without a cast. Conversion from a floating point value to an integer value needs a cast. So does conversion from short values (which are signed) to char values (which are unsigned). Conversion from a boolean value to any other primitive type is not possible.


(a) and (e)

Declaration (b) fails since the method signature only differs in the return type. Declaration (c) fails since it tries to declare an abstract method in a non-abstract class. Declaration (d) fails since its signature is identical to the existing method.


(a) and (d)

The literal 65 is parsed as a value of type int. The value is within the range of the char type. A char literal can be specified by enclosing the character in single quotes ('A'), as a Unicode value in hexadecimal notation ('\u0041'), or as an octal value ('\101'). The octal value cannot exceed '\377'. A char variable cannot be assigned a string, even if the string only contains one character.



Execution proceeds normally and produces no output. All assertions are true.


(b) and (e)

Note that keywords are case sensitive.