Java Generics written test questions and answers
Q1. Which of the following are legal in the underline specified?
______________ = new ArrayList<Integer>(); // line 1 numbers.add(5); //line 2
a) List<? super Integer> numbers
b) List<? super Number> numbers
c) List<Object> numbers
d) List<? extends Integer> numbers
e) List<?> numbers
f) List<Integer> numbers
A1. a and f.
a) is legal because the rule for
<? super T> is
for List<T> to write (i.e. add) to the destination, and does not care if the destination also contain subclasses of T. In the above example T happens to be an Integer.
b) Line 1 is illegal because T is an Integer and not a Number as per the above rule.
c) Line 1 is illegal because the super class of List<T> is List<?> and not List<Object>. List<?> means the collection of the unknown.
d) Line 2 is illegal because the rule for
<? extends T> is
for List<? extends T> is for read only and you can't add to it. It does not care if the actual object retrieved is a sub type of T. In the above example, T happens to be an Integer.
e) Line 1 is illegal because you can't add anything to a list of unknown (i.e. List<?>)
f) is legal as T is Integer.
Note: Illegal means you get compile-time error. Java generics check happens only at compile-time.
Q2. Which of the following are legal in the underline specified?
List<Integer> numbers = ______________________; //Line1 numbers.add(5);
a) new ArrayList<Integer>();
b) new ArrayList<?>();
c) new ArrayList<? super Integer>();
d) new ArrayList<? extends Integer>();
e) new ArrayList<>();
f) new ArrayList<Number>();
g) new ArrayList<Object>();
A2. a and e (only from Java 8, the empty diamond is allowed on instantiation.
b, c, and d are illegal on Line 1 because ? (i.e. the wild card) types cannot be instantiated.
f and g are illegal on Line 1 because T is an Integer, and List<Number> and List<Object> cannot be converted to List<Integer>
Q3. Can you use generics with Java arrays?
A3. No. One of the reasons to favor a List over an Array is because a List supports generics to provide compile time type-safety check.
Q4. What do you understand by the term type erasure?
A4: Generics in Java is implemented using type erasure that happens at compile time. This means a List<Number> becomes just a List at run-time. This was done to preserve backward compatibility.
Q5. Given the following Pair class that takes Generic data types
public class Pair<T, S> { public T first; public S second; public Pair(T a, S b) { first = a; second = b; } }
Which of the following statements compile without errors?
a) Pair<String,Color> colorName = new Pair<String,Color>("Red", Color.RED);
b) Pair<Double,Double> coordinates = new Pair<Double,Double>(17.3,42.8);
c) Pair<String,Double> keyValue = new Pair<String,Double>("PI", "22/7");
d) Pair<String,Double> lookUp = new Pair<>("right-angle", 90.0);
e) Pair<String,String, String> lookUp = new Pair<>("a", "b", "c");
A5. a, b, and d (empty-diamond compiles from Java 8 on wards).
c) won't compile as "22/7" should be of type Double and not String. The constructor expects an object of type Double. Actual error: The constructor Pair<String,Double>(String, String) is undefined
e) won't compile as it expects only two arguments and not three. Actual error: Incorrect number of arguments for type Pair<T,S>; it cannot be parameterized with arguments <String, String, String>
Q6. Given the following implementation to count the number of occurrences of a given item. The example below counts the occurrences of number 6, and returns 3 as the count.
public class OccrrencesTest { public static int countOccurrences(Integer[] list, Integer itemToCount) { int count = 0; if (itemToCount == null) { for (Integer listItem : list) if (listItem == null) count++; } else { for (Integer listItem : list) if (itemToCount.equals(listItem)) count++; } return count; } public static void main(String[] args) { Integer[] numbers = {5,6,6,5,7,8,6}; System.out.println(countOccurrences(numbers, 6)); } }
How will you ensure that the implementation works with other types like String, Color, Double, etc ?
A6. If you want to use the static method approach, you method needs to use the generic method type, for example <T> as shown below. Note that the generic type is also used in the static method signature before the return type int.
public class OccrrencesTest { public static <T> int countOccurrences(T[] list, T itemToCount) { int count = 0; if (itemToCount == null) { for (T listItem : list) if (listItem == null) count++; } else { for (T listItem : list) if (itemToCount.equals(listItem)) count++; } return count; } public static void main(String[] args) { Integer[] numbers = {5,6,6,5,7,8,6}; System.out.println(countOccurrences(numbers, 6)); } }
if you want to use instance method approach
public class OccrrencesTest<T> { public int countOccurrences(T[] list, T itemToCount) { int count = 0; if (itemToCount == null) { for (T listItem : list) if (listItem == null) count++; } else { for (T listItem : list) if (itemToCount.equals(listItem)) count++; } return count; } public static void main(String[] args) { Integer[] numbers = {5,6,6,5,7,8,6}; System.out.println(new OccrrencesTest<Integer>().countOccurrences(numbers, 6)); } }
In both examples, the type of T is inferred at compile-time. Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable.
Color[] numbers = {Color.RED, Color.blue}; System.out.println(new OccrrencesTest<Color>().countOccurrences(numbers, Color.RED));
Labels: generics, Written tests
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home