java left logo
java middle logo
java right logo
 

Home arrow Java SE Tips
 
 
Main Menu
Home
Java Tutorials
Book Reviews
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Java Network
Java Forums
Java Blog




Most Visited Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews
Top Rated Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews


Statistics
Registered Users: 4101
Java SE Tips: 614
Java ME Tips: 202
Java EE Tips: 183
Other API Tips: 779
Java Applications: 298
Java Libraries: 209
Java Games: 16
Book Reviews:
 
 
 
How to use generics E-mail
User Rating: / 23
PoorBest 

This Tech Tip reprinted with permission by java.sun.com

The 5.0 release of J2SE includes the first set of significant language-level changes to the Java platform in some time. In addition to new constructs for things such as the enhance for loop and variable argument lists, J2SE 5.0 provides compile-time type safety with the Java Collections framework through generics in accordance with JSR-14: Add Generic Types To The Java Programming Language.

One of the primary uses of generics is to abstract data types when working with collections. Prior to the JDK 5.0 release, when you created a Collection, you could put anything in it, for example:

   List myList = new ArrayList(10);
   myList.add(new Integer(10));
   myList.add("Hello, World");

If you wanted to restrict your Collection to a specific type, it was difficult at best. Getting items out of the collection required you to use a casting operation:

   Integer myInt = (Integer)myList.iterator().next();

If you accidently cast the wrong type, the program would successfully compile, but an exception would be thrown at runtime. Unless you dealt specifically with everything in the Collection as an Object, casting typically happened blindly -- or by doing an instanceof check before calling the casted operation.

  Iterator listItor = myList.iterator();
  Object myObject = listItor.next();
  Integer myInt = null;
  if (myObject instanceof Integer) {
    myInt = (Integer)myObject;
  }

That situation underscores the beauty of generics. Generics allows you to specify, at compile-time, the types of objects you want to store in a Collection. Then when you add and get items from the list, the list already knows what types of objects are supposed to be acted on. So you don't need to cast anything. The "<>" characters are used to designate what type is to be stored. If the wrong type of data is provided, a compile-time exception is thrown. For example, if you try to compile the following class:

  import java.util.*;

  public class First {
    public static void main(String args[]) {
      List<Integer> myList = new ArrayList<Integer>(10);
      myList.add(10);
      myList.add("Hello, World");
    }
  }

you get an error like this:


   First.java:7: cannot find symbol
   symbol  : method add(java.lang.String)
   location: interface java.util.List
         myList.add("Hello, World");
                 ^
   1 error

This message basically says that there is no add(String) method available when the interface is for a List of Integer objects. The myList.add(10); method did add the Integer object of number 10 to the list. Autoboxing converted the int type to an Integer. It is only the adding of a String to a List of Integer objects that failed here.

If you work with elements of a collection and don't explicitly state the type of elements in that collection, you're warned about that, too. For instance, the following program creates a List, but it doesn't specify what type is to be stored in the List:

   import java.util.*;

   public class Second {
     public static void main(String args[]) {
       List list = new ArrayList();
       list.add(10);
     }
   }

When you compile the program, you get the following warning:

   Note: Second.java uses unchecked or unsafe operations.
   Note: Recompile with -Xlint:unchecked for details.

Yes, that is a warning. If you then follow the directions and add -Xlint:unchecked to the javac command line:

  javac -Xlint:unchecked Second.java

you will see the following added information:

  Second.java:6: warning: [unchecked] unchecked call to add(E) 
         as a member of the raw type java.util.List
    list.add(10);
             ^

The message means that the type of element added to the List, the "E" in the "add(E)" call, was never specified. The message is just a warning though, so a .class file was created.

If you want to get rid of the warning, you can add to the List declaration, as follows:

List<Object> list = new ArrayList<Object>();

Here, Object is the E, and basically says that anything can be stored in the List.

Where does E come from though? If you look at the interface declaration for java.util.List, you see the following:

   public interface List<E> extends Collection<E>

This literally says that it is declaring a List of E's.

Later in the interface definition, you see methods where the argument or return type is replaced by an E:

   Iterator<E" iterator();
   ListIterator<E" listIterator();
   boolean add(E o);
   boolean addAll(Collection<? extends E" c);

Because the E is specified at compile time, you don't have to rely on runtime exceptions to find type mismatches. The ? in the addAll line can be thought of as a collection of unknown, but the unknown would be E or a subclass. This construct allows you to work with collections of subclasses, and not simply exact matches.

Although not fully explored in the first example, generics is commonly used with the enhanced for loop, with an iterator. Without generics, looping through a List of String objects requires you to cast each element retrieved from the List to the appropriate type. However things get simpler with generics and the enhanced for loop.

Here's the old way of looping through a List of String objects, that is, without generics and an enhanced for loop:

   import java.util.*;

   public class Old {
     public static void main(String args[]) {
       List list = Arrays.asList(args);
       Iterator itor = list.iterator();
       while (itor.hasNext()) {
         String element = (String)itor.next();
         System.out.println(element + " / " + element.length());
       }
     }
   }   

If you compile and run the Old class and then run it with a string, like this:

   java Old Hello

you get:

   Hello / 5

With JDK 5.0, you can combine the new enhanced for loop construct with generics to create a program that is type-safe at compile-time, and is more readable and more maintainable. Here's what looping through a List of String objects looks like if you use generics and an enhanced for loop:

   import java.util.*;

   public class New {
     public static void main(String args[]) {
       List<String> list = Arrays.asList(args);
       for (String element : list) {
         System.out.println(element + " / " + element.length());
       }
     }
   }
   java New Hello
   Hello / 5

As demonstrated here, generics and the enhanced for loop work well together.

For more information on generics, see:

  1. Tutorial: Generics in the Java Programming Language (pdf)
  2. JSR-14: Add Generic Types To The Java Programming Language
  3. Generics

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.


 Related Tips

 
< Prev   Next >

Page 1 of 0 ( 0 comments )

You can share your information about this topic using the form below!

Please do not post your questions with this form! Thanks.


Name (required)


E-Mail (required)

Your email will not be displayed on the site - only to our administrator
Homepage(optional)



Comment Enable HTML code : Yes No



 
       
         
     
 
 
 
   
 
 
java bottom left
java bottom middle
java bottom right
RSS 0.91 FeedRSS 1.0 FeedRSS 2.0 FeedATOM FeedOPML Feed

Home - About Us - Privacy Policy
Copyright 2005 - 2008 www.java-tips.org
Java is a trademark of Sun Microsystems, Inc.