| In the Collections discussion we 
              noted that object containers expect to hold java.lang.Object 
              types and that the returned Object 
              types must be cast into the desired type. The new J2SE 5.0 includes 
              the very significant addition of generics feature in which 
              object containers can actually know what object type they 
              should hold. Then any attempt to insert an object of the wrong type 
              results in a compile-time error rather than a runtime ClassCastException. 
             Generics is a large an important addition to Java, and we only 
              scratch the surface of how to use generics. Generic features pervade 
              all the Collection Framework classes 
              as well as several other APIs in J2SE 5.0.  We use the ArrayList 
              class to illustrate the generics capability. Suppose we have a list 
              of strings  
              List list_of_strings 
                = new ArrayList ();  Without generics, we can insert any Object 
              type into the list - String, 
              Integer, 
              etc. With generics, we declare the type of object the list is allowed 
              to contain at compile time. The syntax is as follows:  
               List<String> 
                list_of_strings = new ArrayList<String> ();  The  <String> 
              notation indicates that this particular List 
              object is only allowed to contain String 
              types. Any attempt to add an Integer 
              (autoboxed or not) or any other object type is disallowed at compile 
              time.  
               list_of_strings.add 
                ("this is legal");list_of_strings.add (new Integer (5)); // this is not allowed
 list_of_strings.add (5); // neither is this
  In the first illegal add(), 
              we explicitly wrap the 5 
              into an Integer. 
              Integer 
              is an Object 
              type and so could be added to a plain List, 
              but it is not permitted to be added to the List<String> 
              object container.In the second attempt, neither is the int 
              5 permitted. The compiler errors you will see look like this:  
               Generics.java:7: 
                cannot find symbolsymbol : method add (java.lang.Integer)
 location: interface java.util.List<java.lang.String>
 list.add (new 
                Integer (5));
 ^
 Generics.java:8: cannot find symbol
 symbol : method add (int)
 location: interface java.util.List<java.lang.String>
 list.add (5);
 ^
  The compiler is saying that it cannot find an add() 
              method that takes an Integer 
              type in the interface java.util.List. 
              And it says there is not an add() 
              that takes an int.  By adding the generic type notation  (also known as a 
              parameterized type) we have effectively created a new List 
              interface that permits only String 
              inserts. (Note that the second illegal add() 
              did not autobox the int 
              5 into an Integer. 
              Doing so would not have worked either since the first illegal attempt 
              already demonstrated that adding an Integer 
              is not permitted.)  Where generics becomes important and saves a lot of code is when 
              iterating over generic types and, in particular, in conjunction 
              with autoboxing and unboxing 
              of primitive types. Recall that without generics we must cast returned 
              Object types 
              into the desired type during an iteration. That was with J2SE 1.4 
              and below. With J2SE 5.0, the collection object "knows" what type 
              it holds, so it returns that type instead of the Object 
              type.   Without generics, iterating through a list of strings and printing 
              each out required code like this  
               List list_of_strings 
                = new ArrayList ();...
 for (Iterator it = list_of_strings.iterator (); it.hasNext ();) 
                {
 String s = (String) it.next ();
 Sytem.out.println (s);
 }
  But when 
              list_of_strings is a List type, this simplifies to  
               for (Iterator 
                it = list_of_strings.iterator (); it.hasNext ()) {String s = it.next ();
 Sytem.out.println (s);
 }
  We see that no explicit casting is needed.  With autoboxing and unboxing, we can insert and retrieve primitive 
              types without explicitly using the wrapper objects.  
               List<Integer>
                list_of_ints = new ArrayList<Integer> ();...
 for (Iterator it = list_of_ints.iterator (); it.hasNext ();) {
 int i = it.next ();
 ...
 }
  We should warn you of a nuisance with the J2SE 5.0 compiler. The 
              use of these special type-safe containers removes a significant 
              source of errors. For backward compatibility, all the old containers 
              are still available. So any pre-5.0 code continues to work exactly 
              the same in 5.0 and beyond. However, because the old container types 
              are potentially unsafe, the 5.0 javac compiler now issues warnings 
              about possible unsafe usage whenever it encounters one of the old 
              container types.  These are just warnings and can be ignored if you are sure that 
              the code is safe. The best way to get rid of the warnings is to 
              switch to the use of the generic types where appropriate.  Of course, sometimes the old non-type-safe containers are needed, 
              such as when you really want to insert a mix of object types. In 
              this case, you can just ignore the warnings. Alternatively, the 
              metadata (annotation) system discussed in Chapter 
              1: Supplements and Chapter 
              4: Supplements provides an @SuppressWarnings 
              annotation to explicitly suppress such warnings. Generics and the Enhanced 
              For-Loop. Note that generics allows for the enhanced for loop (or for-each 
              loop) discussed in Chapter 
              2: Supplements. to work with Collections containers. It offers 
              an elegant alternative to the Iterator 
              type loop in many cases. For example, the following snippet     ArrayList<string> 
              array_list = new ArrayList<string> ();array_list.add ("Abc");
 array_list.add ("Def");
 array_list.add ("Ghi");
 
 for (String str : array_list)
 System.out.println (str);
  gives an output as follows:   AbcDef
 Ghi
 Specifying the ArrayList variable as 
              a String container means that the string 
              parameter in the loop will always be assigned the correct type. 
             References & Web Resources Latest update: Oct. 19, 2005
 |