Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

Section 14. Generics

14. Generics

14.1(b)

The type of lst is List of Integer and the type of numList is List of Number. The compiler issues an error because List<Integer> is not a subtype of List<Number>.

14.2(f)

Assigning bList, a reference of a non-generic list, to oList, a reference of a generic list, in (2) results in an unchecked conversion warning.

14.3(c)

We can only get an Object from a List<? super Integer>. The list could contain Comparable objects, and Number does not implement Comparable.

14.4(b)

The compiler issues an unchecked conversion warning in (1), as we are assigning a raw list to a generic list.

14.5(b), (f), and (g)

We cannot refer to the type parameters of a generic class in a static context, e.g., in static initializer blocks, static field declarations, and as types of local variables in static methods. Also we cannot create an array of a type parameter, as in (2).

14.6(e)

Any generic list can be assigned to a raw list reference. A raw list and an unbounded wildcard list are assignment compatible.

14.7(b), (c), (e), and (f)

In (b), (c), (e), and (f), the parameterized type in the object creation expression is a subtype of the type of the reference. This is not the case in (a): just because HashMap<Integer, String> is a subtype of Map<Integer, String>, it does not follow that HashMap<Integer, HashMap<Integer, String>> is a subtype of Map<Integer, Map<Integer, String>>—there is no subtype covariance relationship between concrete parameterized types. In (d) and (g), wild cards cannot be used to instantiate the class.

14.8(b)

ArrayList<Fruit> is not a subtype of List<? extends Apple>, and ArrayList<Apple> is not a subtype of List<? super Fruit>. Any generic list can be assigned to a raw list reference. A raw list and an unbounded wildcard list are assignment compatible.

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

(a), (b) and (c) The compiler will report unchecked call warnings.

(d) Incompatible types, assigning type Object to type String.

(e) From any list, we are guaranteed to get an Object.

14.10(b)

(a) Primitive types are not permitted as type parameters.

(c) String is not a generic class.

(d) The interface Map cannot be instantiated.

(e) The method call accounts.getNum(name) returns an Object, which cannot be converted to a Long.

14.11(d)

The compiler issues unchecked warnings for calls to the add() method. The TreeSet class orders elements according to their natural ordering. A ClassCastException is thrown at runtime, as Strings are not comparable to Integers.

14.12(a) and (b)

The type of reference g is of raw type Garage. We can put any object in such a garage, but only get Objects out. The type of value returned by the get() method in statements (6) - (8) is Object and, therefore, not compatible for assignment to Vehicle, Car, and Sedan.

14.13(b) and (c)

The type of reference g is of Garage<Car>. We can put a Car (or its subtype) in such a garage and get a Car (or its supertype) out. The type of value returned by the get() method in statement (8) is Car and, therefore, not compatible for assignment to Sedan.

14.14(c)

The type of reference g is of Garage<?>. We cannot put any object in such a garage, and can only get an Object out. The type of value returned by the get() method in statements (6) - (8) is (capture-of ?), i.e., some unknown type and, therefore, not compatible for assignment to Vehicle, Car, and Sedan, as the value might turn out to be of a totally unrelated type. For more details on wildcard capture, see Section 14.9, p. 705.

14.15(c)

The type of reference g is of type Garage<? extends Car>. We cannot put any car in such a garage, and can only get a Car (or its supertype) out. The type of value returned by the get() method in statement (8) is (capture-of ? extends Car), i.e., some unknown subtype of Car and, therefore, not compatible for assignment to Sedan, as the value might turn out be of a type totally unrelated to Sedan. For more details on wildcard capture, see Section 14.9, p. 705.

14.16(b) and (c)

The type of reference g is of type Garage<? super Car>. We can put a Car (or its subtype) in such a garage, but can only get Objects out. The type of value returned by the get() method in statements (6)-(8) is (capture-of ? super Car), i.e., some supertype of Car and, therefore, not compatible for assignment to Vehicle, Car, and Sedan, as it might be a value of a supertype of Vehicle, Car, or Sedan, respectively. For more details on wildcard capture, see Section 14.9, p. 705.

14.17(b), (d), and (e)

(a) R cannot be resolved.

(b) Ok.

(c) The ClassA is parameterized with only one type parameter.

(d) Ok.

(e) Ok. The declaration says that the parameterized type ClassA<Number> is the supertype of ClassF<U> for any concrete type U that satisfies the constraint U extends Comparable<U> & Serializable. In the code below, String satisfies the constraint. However the target in the first declaration is of the supertype ClassA<Number>, but this is not the case in the second declaration.

ClassA<Number> ref1 = new ClassF<String>(); // OK
ClassA<Integer> ref2 = new ClassF<String>();// Not OK

(f) The keyword implements cannot be used to specify bounds.

(g) A wildcard cannot be used to specify the type parameter for the superclass.

(h) String is Comparable<String>, therefore, Comparable cannot be implemented more than once with different arguments, i.e., as a bound for U.

(i) From the declaration, superclass ClassA<Integer> implements Comparable<Integer>. Subclass ClassJ thus implements Comparable<Integer>. However, Comparable cannot be implemented more than once with different arguments, i.e., as Comparable<Number> in the declaration.

14.18(a) and (e)

In (b) and (c), we cannot add any object to the list as the list is of an unknown type. From a list of an unknown type, we are only guaranteed to get an Object. In (d) capture-of ? cannot be converted to String.

14.19(b)

It is the fully qualified name of the class after erasure that is printed at runtime. Note that it is the type of the object, not the reference, that is printed. The erasure of all the lists in the program is ArrayList.

14.20(b) , (e), and (f)

(a) and (d) Incompatible types for assignment: cannot convert from List<Integer> to ArrayList<Integer>.

(c) Incompatible types for assignment: cannot convert from List<Integer> to List<Number>.

14.21(e)

(a) Incompatible types for assignment in the main() method: cannot convert from Collection<capture-of ? extends CharSequence> to Collection<String>.

(b) Incompatible return value in the delete4LetterWords() method: cannot convert from Collection<E> to List<E>.

(c) In the for(:) loop, the component type of words (capture-of ? CharSequence) cannot be converted to E.

(d) In the for(:) loop, the component type of words (capture-of ? CharSequence) cannot be converted to E. Incompatible return value in the delete4LetterWords() method: cannot convert from Collection<E> to List<E>.

(e) OK.

(f) Keyword super cannot be used in a constraint. It can only be used with a wildcard (?).

14.22(c)

(a) Cannot instantiate the interface List.

(b) and (d) The method call ds.add(row) expects a list with element type ArrayList<Integer>, but row has the type List<Integer>.

(e) Incompatible types for assignment: cannot convert from ArrayList<ArrayList<Integer> to List<List<Integer>.

(f) The interface List requires a single type parameter, and it cannot be instantiated.

(g), (h) Both the interface List and the class ArrayList require a single type parameter.

14.23(b) and (f)

After erasure, the method at (1) has the signature overloadMe(List, List). Since all methods are declared void, they must differ in their parameter list after erasure in order to be overloaded with the method at (1). All methods have different parameter lists from that of the method at (1), except for the declarations (b) and (f). In other words, all methods have signatures that are not override-equivalent to the signature of the method at (1), except for (b) and (f).

If one considers the declarations (a) and (e) on their own, these two methods have the same signature overloadMe(Collection, List) after erasure and, therefore, would not be overloaded, i.e., they would be override-equivalent.

14.24(c) and (d)

(a) The method appendAndWrite(Collection<T>, T) cannot be applied to the inferred argument type (List<capture-of#n ?>, String). We cannot add to a collection of type Collection<?>.

(b) The method appendAndWrite(Collection<T>, T) cannot be applied to the inferred argument type (List<capture-of#m ? extends Object>, String). We cannot add to a collection of type Collection<? extends Object>.

(c) The method appendAndWrite(Collection<T>, T) can be applied to the inferred argument type (List<capture-of#k ? super Object>, String). T is Object. We can add any object to a collection of type Collection<? super Object>.

(d) The method appendAndWrite(Collection<T>, T) can be applied to the inferred argument type (List<Object>, String). T is Object. We can add any object to a collection of type Collection<Object>.

14.25(b)

Passing a raw list to either a list of Integers or to a list of type parameter T is not type-safe.

14.26(d), (e), and (f)

(a) The arguments in the call are (List<Number>, List<Integer>). No type inferred from the arguments satisfies the formal parameters (List<? extends T>, List<? super T>).

(b) The arguments in the call are (List<Number>, List<Integer>). The actual type parameter is Number. The arguments do not satisfy the formal parameters (List<? extends Number>, List<? super Number>). List<Number> is a subtype of List<? extends Number>, but List<Integer> is not a subtype of List<? super Number>.

(c) The arguments in the call are (List<Number>, List<Integer>). The actual type parameter is Integer. The arguments do not satisfy the formal parameters (List<? extends Integer>, List<? super Integer>). List<Number> is not a subtype of List<? extends Integer>, although List<Integer> is a subtype of List<? super Integer>.

(d) The arguments in the call are (List<Integer>, List<Number>). The inferred type is Integer. The arguments satisfy the formal parameters (List<? extends Integer>, List<? super Integer>).

(e) The arguments in the call are (List<Integer>, List<Number>). The actual type parameter is Number. The arguments satisfy the formal parameters (List<? extends Number>, List<? super Number>).

(f) Same reasoning as in (d), but the actual type parameter is explicitly specified in the method call.

14.27(e)

The methods in (1), (2), and (3) are not generic, but the methods in (4) and (5) are. A generic method need not be declared in a generic class. Regardless of what type an object has, it is still an Object.

14.28(a) and (b)

(a) The class uses the correct syntax to declare the constructors.

(b) The constructors in (2) and (3) have the same erasure and, therefore, only one of them can be declared, i.e., we have a name clash. The compiler reports an error.

(c) A generic class can declare generic constructors, as in (3) and (4).

(d) A type parameter declared by the class can be ignored in the class body.

14.29(h)

(a) Invokes the default constructor at (1).

(b) Invokes the constructor at (2) with T as String and V as String.

(c) Invokes the constructor at (2) with T as Integer and V as String.

(d) Invokes the constructor at (2) with T as Integer and V as Integer.

(e) Invokes the constructor at (2) with T as String and V as String, same as (b).

(f) Invokes the constructor at (3) with T as Integer and V as String. The constructor requires parameters (Integer, String), which is compatible with the arguments (Integer, String) in the constructor call.

(g) Invokes the constructor at (3) with T as Integer and V as String, same as (f).

(h) T is Integer and V is String. The constructor requires parameters (Integer, String), which is not compatible with the arguments (String, Integer) in the constructor call.

14.30(a), (e), and (i)

The erasure of the signature of (2) is different from the erasure of the signature of (1), i.e., overloaded, since signatures are not override-equivalent. Therefore, of the three alternatives (a), (b), and (c), only (a) is correct.

The signature of (3) is the same as the erasure of the signature of (1), i.e., overridden. Therefore, of the three alternatives (d), (e), and (f), only (e) is correct.

The erasure of the signature of (5) is the same as the signature of (4), and not the other way around, i.e., name clash. Therefore, of the three alternatives (h), (i), and (j), only (i) is correct.

14.31(c), (f), (i), and (k)

The type parameter N in SubC1 does not parameterize the supertype SupC. The erasure of the signature of (3) is the same as the erasure of the signature of (1), i.e., name clash. Therefore, of the three alternatives (a), (b), and (c), only (c) is correct.

The type parameter N in SubC1 cannot be guaranteed to be a subtype of the type parameter T in SupC, i.e., incompatible return types for get() methods at (4) and (2). Also, methods cannot be overloaded if only return types are different. Therefore, of the three alternatives (d), (e), and (f), only (f) is correct.

The type parameter N in SubC2 is a subtype of the type parameter M which parameterizes the supertype SupC. The erasure of the signature of (5) is still the same as the erasure of the signature of (1), i.e., name clash. Therefore, of the three alternatives (g), (h), and (i), only (i) is correct.

The type parameter N in SubC1 is a subtype of the type parameter T (through M) in SupC, i.e., covariant return types for the get() methods at (6) and (2), which are overridden. Therefore, of the three alternatives (j), (k), and (l), only (k) is correct.

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

(a) An enum type and its enum values are static. Since type parameters cannot be used in any static context, the parameterization of an enum type would be nonsense.

(c) Generic exceptions or error types are not allowed, because the exception handling mechanism is a runtime mechanism and the JVM is oblivious of generics.

(e) Anonymous classes do not have a name, but a class name is needed for declaring a generic class and specifying its type parameters.

14.33(c)

The type parameter E in the class Tantrum has the upper bound Exception, and the method throwOne() can throw an exception that is a subtype of Exception.

The generic Tantrum class is instantiated correctly in the main() method, as is the non-generic class TantrumException that is a subtype of Exception.

14.34(d)

Casts are permitted, as in (2)-(6), but can result in an unchecked warning. The assignment in (5) is from a raw type (List) to a parameterized type (List<Integer>), resulting in an unchecked assignment conversion warning. Note that in (5) the cast does not pose any problem. It is the assignment from generic code to legacy code that can be a potential problem, flagged as an unchecked warning.

In (6), the cast is against the erasure of List<Integer>, that is to say, List. The compiler cannot guarantee that obj is a List<Integer> at runtime, it therefore flags the cast with an unchecked warning.

Only reifiable types in casts do not result in an unchecked warning.

14.35(e)

Instance tests in the scuddle() method use the reified type List<?>. All assignments in the main() method are type-safe.

14.36(e), (f), (g), and (h)

The correct answers all create arrays that have a component type that is reifiable, and the assignment types are compatible.

(a) Cannot instantiate a type parameter.

(b) Cannot create an array whose component type is a type parameter.

(c) Cannot create a generic array of List<T>, as List<T> is not reifiable type..

(d) Cannot create an array of a type parameter.

(i) Unchecked assignment conversion warning, as the assignment is from a non-generic type to a generic type.

14.37(c)

Erasure of E[] in the method copy() is Object[]. The array type Object[] is actually cast to Object[] at runtime, i.e., an identity cast. The method copy() returns an array of Object. In the main() method, the assignment of this array to an array of Strings results in a ClassCastException.

14.38(e)

The method header in (1) is valid. The type of the varargs parameter can be generic. The type of the formal parameter aols is an array of Lists of T. The method prints each list.

The main() method in (2) can be declared as String..., as it is equivalent to String[].

The statement at (3) creates an array of Lists of Strings. The type parameter T is inferred to be String in the method call in (4).


  

You are currently reading a PREVIEW of this book.

                                                                                                                    

Get instant access to over $1 million worth of books and videos.

  

Start a Free Trial


  
  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint