Skip to main content

Java Tech: Generics and You

November 10, 2005

{cs.r.title}









Contents
Take the Test
Review and Compare
Conclusion
Resources
Answers to Previous Homework

How much do you know about generics? Based on your amount of
generics knowledge, are you comfortable with having to maintain
another developer's generified code, should your project manager
tell you to do so? Perhaps you have not taken the time to determine
how much you know about generics and how much you still have to
learn. If you would like to assess your generics I.Q., you might
find this article a helpful test of your generics knowledge.

Note: This article bases its content on a very useful and
extensive generics FAQ that I discovered a couple of months ago.
After you finish this article, do yourself a favor by checking out
the FAQ, listed in the Resources section at the end of
the article.

Take the Test

This section presents a test on several generics concepts. The
test's 20 questions are a mixture of fill in the blank, true/false,
multiple choice, and long answer. Take all the time you need to
complete this test, but resist the urge to peek at the answers
(which I present in the next section) until you finish. The test
begins now.

  1. Generics identifies language features for defining and using
    ________________ and ________________.

  2. What is a parameterized type?

  3. How does generics promote type safety?

  4. Which of the following reference types cannot be generic?

    1. Anonymous inner class
    2. Interface
    3. Inner class
    4. All of the above
  5. True or false: Set<Object> is the supertype
    of Set<String>.

  6. What is a type parameter?

  7. A ________________ describes a family of types and is used as a
    type parameter.

  8. How is a concrete parameterized type different from a
    non-concrete parameterized type?

  9. True or false: parameterized types have type parameters.

  10. Which syntax would you use to express a wildcard with a lower
    bound of some type?

    1. ?
    2. ? extends type
    3. ? super type
    4. None of the above
  11. Identify those types that cannot be used as type arguments.

  12. Why can you not derive (directly or indirectly) generic classes
    from Throwable?

  13. What is type erasure?

  14. Identify the tasks performed by type erasure.

  15. True or false: The parameterized types List<Date>
    and List<?> share the same runtime type.

  16. The opposite of type erasure is known as ________________.

  17. Which overloaded method is called by the following program?

    [prettify]// Overload.java
    
    import java.util.Date;
    
    public class Overload
    {
       public static void someOverloadedMethod (Object o)
       {
          System.out.println
            ("call to someOverloadedMethod(Object o)");
       }
    
       public static void someOverloadedMethod (Date d)
       {
          System.out.println
            ("call to someOverloadedMethod(Date d)");
       }
    
       public static &lt;T&gt; void methodCaller (T t)
       {
          someOverloadedMethod (t);
       }
    
       public static void main (String [] args)
       {
          methodCaller (new Date ());      
       }
    }
    [/prettify]
  18. What is an "unchecked" warning message?

  19. When the compiler reports an unchecked or unsafe operation, it
    also tells you to recompile with the ________________ option to
    obtain details.

  20. True or false: the code fragment

    System.out.println (o instanceof
    Set<String>);
    will compile.







Review and Compare

Now that the test is over, it's time to find out how well you
understand generics. This section repeats the questions stated in
the previous section, but it also presents the answers (in red) to
those questions. Review those answers and compare them to your
responses. Give yourself one mark for each correctly answered
question. If you believe you got a question partially right, give
yourself half of one mark. Add up the marks and multiply by 5 to
receive your test score.

  1. Generics identifies language features for defining and using
    generic types and "#CC0033">generic methods.

  2. What is a parameterized type?

    A parameterized type is an instance
    of a generic type. Example: HashMap<K,V> is a
    generic type and HashMap<String,Double> is an
    instance of that type--a parameterized type.

  3. How does generics promote type safety?

    Prior to J2SE 5, Java's Collections
    framework did not provide for homogeneous
    collections
    --collections whose elements all share the same
    type. Collections held Object references, raising the
    possibility of heterogeneous collections--collections
    with elements of different types. Collection APIs revealed this
    heterogeneous bent by accepting arbitrary elements for insertions,
    and by returning Object references when retrieving
    elements from collections.

    The problem with heterogeneous
    collections: lack of type safety. Because a retrieval operation
    requires a cast operation, to downcast from Object to
    the returned object's type, before assigning the returned object to
    a variable of that type, there is a potential for a
    ClassCastException, should an object not match or
    subtype that type. The following code fragment illustrates this
    problem:

    [prettify]<font color="#CC0033"> 
    List integers = new ArrayList ();
    
    integers.add (new Integer (25));
    integers.add (new Integer (-367));
    integers.add (BigInteger.ONE);
    
    Iterator it = integers.iterator ();
    while (it.hasNext ())
    {
       Integer i = (Integer) it.next ();
    
       // Do something with i
    }</font>
    [/prettify]

    The code fragment is problematic because
    of the (Integer) cast. That cast signifies our
    assumption that integers is a homogeneous collection
    of Integer objects. But that is not the case: there is
    nothing to prevent us from adding BigIntegers (or
    other kinds of objects) to integers. When retrieving
    the BigInteger from the collection, that cast results
    in a thrown ClassCastException: we cannot cast from
    BigInteger to Integer.

    To avoid ClassCastExceptions,
    we need to prevent non-Integer objects from being
    added to the List. Generics lets us accomplish that
    task. Consider the following code fragment:

    [prettify]<font color="#CC0033"> 
    List&lt;Integer&gt; integers = new ArrayList&lt;Integer&gt; ();
    
    integers.add (new Integer (25));
    integers.add (new Integer (-367));
    integers.add (BigInteger.ONE);
    
    Iterator&lt;Integer&gt; it = integers.iterator ();
    while (it.hasNext ())
    {
       Integer i = it.next ();
    
       // Do something with i
    }</font>
    [/prettify]

    Unlike the previous code fragment, which
    uses the raw List type to create an object
    representing a heterogeneous List, this code fragment
    uses generics to create a parameterized
    List<Integer> type. That type's
    integers object represents a homogeneous
    List of Integers. The compiler, which has
    access to this type information, displays an error message when
    encountering integers.add (BigInteger.ONE);:
    List<Integer> has no method for adding a
    BigInteger to a List of
    Integers.

    Because integers has
    the List<Integer> type, its iterator()
    method returns an object of Iterator<Integer>
    type. This object's next() method will only return
    Integer objects; a cast is not required (which reduces
    source code clutter) and a ClassCastException cannot
    occur. By providing static type information, so that the compiler
    can enforce a homogeneous List of
    Integers, generics has made this code
    type-safe.

  4. Which of the following reference types cannot be generic?

    1. Anonymous inner class
    2. Interface
    3. Inner class
    4. All of the above
  5. True or false: Set<Object> is the supertype
    of Set<String>.

    False. There is no type relationship between
    different instances of the same generic type for different concrete
    type arguments.

  6. What is a type parameter?

    A type parameter is a stand-in for
    a type argument. For example, the E in

    public
    class TreeSet<E>
    is a type parameter. It will be
    replaced with a type argument when creating an instance of a
    generic type. Example:
    new
    TreeSet<String>
    .

  7. A wildcard describes a family of
    types and is used as a type parameter.

  8. How is a concrete parameterized type different from a
    non-concrete parameterized type?

    A concrete parameterized type cannot have
    wildcards as its type arguments. Wildcards are permitted for
    non-concrete parameterized types.

  9. True or false: parameterized types have type parameters.

    False. Parameterized types, which are
    instances of generic types, have type arguments.

  10. Which syntax would you use to express a wildcard with a lower
    bound of some type?

    1. ?
    2. ? extends type
    3. ? super
      type
    4. None of the above
  11. Identify those types that cannot be used as type arguments.

    All primitive types, such as
    int, char, and double,
    cannot be used as type arguments. In contrast, all references
    types, including parameterized types (such as
    ArrayList<Set<String>>), can be used as
    type arguments.

  12. Why can you not derive (directly or indirectly) generic classes
    from Throwable?

    Generics-based exception and error classes
    are not allowed because the exception-handling mechanism is
    JVM-based and the JVM knows nothing about generics.

  13. What is type erasure?

    Type erasure is a compiler activity where
    all instances of a generic type or a generic method are mapped to
    the unique bytecode representation of the generic type or generic
    method.

  14. Identify the tasks performed by type erasure.

    Type erasure 1) elides type parameters
    (upon encountering a generic type definition or a generic method
    definition, the compiler removes all type parameters and replaces
    them with their leftmost bound or the Object type, if
    there is no bound), and 2) elides type arguments (upon encountering
    a parameterized type, the compiler removes all type
    arguments--List<Integer> is translated to
    List, for example).

  15. True or false: the parameterized types List<Date>
    and List<?> share the same runtime type.

    True. All parameterized versions of
    List (including the List raw type) are
    represented by the same Class object, which serves as
    the runtime type.

  16. The opposite of type erasure is known as "#CC0033">reification.

  17. Which overloaded method is called by the following program?

    [prettify]// Overload.java
    
    import java.util.Date;
    
    public class Overload
    {
       public static void someOverloadedMethod (Object o)
       {
          System.out.println
            ("call to someOverloadedMethod(Object o)");
       }
    
       public static void someOverloadedMethod (Date d)
       {
          System.out.println
            ("call to someOverloadedMethod(Date d)");
       }
    
       public static &lt;T&gt; void methodCaller (T t)
       {
          someOverloadedMethod (t);
       }
    
       public static void main (String [] args)
       {
          methodCaller (new Date ());      
       }
    }
    [/prettify]

    Although you might think otherwise, the
    program above calls someOverloadedMethod(Object o).
    This method, instead of someOverloadedMethod(Date d),
    is called because overload resolution happens at compile time, when
    the generic method is translated to its unique bytecode
    representation, and type erasure (which takes care of that mapping)
    causes type parameters to be replaced by their leftmost bound or
    Object (if there is no bound). After type erasure, we
    are left with the following non-generic method:

    [prettify]<font color=
    "#CC0033">public static void methodCaller (Object t)
    {
       someOverloadedMethod (t);
    }</font>
    [/prettify]
  18. What is an "unchecked" warning message?

    Occasionally, you may encounter a compiler
    warning message stating that an operation is unchecked. For
    example, you may be told about an unchecked call to an
    add(E) method. This "unchecked" warning message is due
    to the compiler and runtime system not having sufficient type
    information to ensure type safety.

    The use of raw types (especially in legacy
    code) serves as the most likely culprit of "unchecked" warning
    messages. Because raw types don't provide enough type information,
    it is impossible for the compiler to perform all of its needed type
    checks. Consider the code fragment below:

    [prettify]<font color="#CC0033">Map colors = new HashMap ();
    
    colors.put ("red", Color.red);</font>
    [/prettify]

    The code fragment concerns itself with
    mapping AWT-based Color objects to descriptive names,
    which are represented by String objects. When you
    compile this code, the compiler reveals the following warning
    message:

    [prettify]<font color=
    "#CC0033">warning: [unchecked] unchecked call to put(K,V)
    as a member of the raw type java.util.Map</font>
    [/prettify]

    Map's put()
    method invocation causes a problem for the compiler. It does not
    know if it's safe to put an entry, consisting of a
    String-based key and a Color-based value,
    into the Map. The raw Map type's lack of
    specific type information for its entries makes this call unsafe,
    and so the compiler reports the warning. Of course, changing
    colors' declaration to

    Map<String,Color>
    colors = new HashMap<String,Color> ();
    provides this
    information; the warning is no longer necessary.

  19. When the compiler reports an unchecked or unsafe operation, it
    also tells you to recompile with the "#CC0033">-Xlint:unchecked option to obtain details.

  20. True or false: the

    System.out.println (o instanceof
    Set<String>);
    code fragment will compile.

    False. The code fragment will not compile
    because Set<String> does not have an exact
    runtime type representation. Following type erasure, the runtime
    type becomes the raw type Set. Because
    instanceof can only check against Set,
    and not Set<String>, confusion results. To
    prevent this confusion, the compiler disallows the code
    fragment.

Conclusion

After obtaining your test score, you might be feeling depressed
or elated. If you received a low score, this does not mean you are
a loser when it comes to generics. Instead, the score means you
have lots of learning to do; this is important if you might be
called upon to maintain another developer's generified code. On the
other hand, receiving a high score does not mean you have little
else to learn about generics. All tests present samples of subject
material, and this test is no different. If you are deficient in a
category that the test has not covered, that deficiency will not be
revealed by the test. Regardless of your score, I hope that you
have found this test to be enlightening, and I hope that it
enhances your understanding of generics.

Resources

Answers to Previous Homework

The "http://today.java.net/pub/a/today/2005/08/30/bluej.html">previous
Java Tech article
presented you with some challenging homework
on BlueJ. Let's revisit that homework and investigate
solutions.

  1. For space reasons, I was unable to dig into BlueJ's support for
    applets. Therefore, your new homework is to investigate BlueJ's
    applet support and answer the following questions: how do you
    create an applet in BlueJ? And can you set breakpoints in the
    applet?

    Create an applet first by clicking the project toolbar's New
    Class... button, and next by selecting the resulting Create New
    Class dialog box's Applet radio button. Although you can set
    breakpoints in the applet, they will have no effect during the
    applet's execution in a web browser or in the
    appletviewer--those tools have their own virtual machines, and
    those virtual machines don't recognize breakpoints.

width="1" height="1" border="0" alt=" " />
Jeff Friesen is a freelance software developer and educator specializing in Java technology. Check out his site at javajeff.mb.ca.
Related Topics >> Programming   |