| By Jess Garms, Tim Hanson | Article Rating: |
|
| February 6, 2006 11:30 AM EST | Reads: |
33,219 |
Generic Methods
In addition to generic types, 1.5 introduced generic methods. In this example from java.util.Collections, a singleton list is constructed. The element type of the new list is inferred based on the type of the object passed into the method:
static <T> List<T> Collections.singletonList(T o)
Example usage:
public List<Integer> getListOfOne() {
return Collections.singletonList(1);
}
In the example usage, we pass in an int. The return type of the method is then List<Integer>. The compiler infers Integer for T. This is different from generic types because you don't generally need to explicitly specify the type argument.
This also shows interaction of autoboxing with generics. Type arguments must be reference types, that's why we get List<Integer> and not List<int>.
Generic Methods Without Parameters
The emptyList() method was introduced with generics as a type-safe replacement for the EMPTY_LIST field:
static <T> List<T> Collections.emptyList()
Example usage:
public List<Integer> getNoIntegers() {
return Collections.emptyList();
}
Unlike the previous example, this one has no parameters, so how does the compiler infer the type for T? Basically, it will try once using the parameters. If that does nothing, it tries again using the return or assignment type. In this case, we are returning List<Integer>, so T is inferred to be Integer.
What if you are invoking a generic method in a place other than in a return statement or assignment statement? Then the compiler is unable to do the second pass of type inferencing. In this example, emptyList() is invoked from within the conditional operator:
public List<Integer> getNoIntegers() {
return x ? Collections.emptyList() : null;
}
The compiler cannot see the return context, and cannot infer T, so it would give up and assume Object. You would see an error message like "cannot convert List<Object> to List<Integer>".
To fix this, you explicitly pass the type argument to the method invocation. Then the compiler won't try to infer the type arguments for you, and you get the right result:
return x ? Collections.<Integer>emptyList():null;
The other place where this will happen frequently is in method invocation. If a method takes a List<String> and you try to call this passing emptyList() for that param, you would also need to use this syntax.
Beyond Collections
Here are three examples of generic types that are not collections that use generics in a novel way. All of these come from the standard Java libraries.
- Class<T>: Class is parameterized on the type of the class. This make it possible to construct a newInstance without casting.
- Comparable<T>: Comparable is parameterized by the actual comparison type. This provides stronger typing on compareTo() invocations. For example, String implements Comparable<String>. Invoking compareTo() on anything other than a String will fail at compile time.
- Enum<E extends Enum<E>>: Enum is parameterized by the enum type. An enum called Color would extend Enum<Color>. The getDeclaringClass returns the class object for the enum type. It's different from getClass(), which may return an anonymous class.
The most complex part of generics is understanding wildcards. We'll cover the three types of wildcards and why you might want to use them.
First let's look at how arrays work. You can assign a Number[] from an Integer[]. If you attempt to write a Float into the Number[], it will compile but fail at runtime with an ArrayStoreException:
Integer[] ia = new Integer[5];
Number[] na = ia;
na[0] = 0.5; // compiles, but fails at runtime
If we try to translate that example directly into generics, it fails at compile time because the assignment isn't allowed:
List<Integer> iList = new ArrayList<Integer>();
List<Number> nList = iList; // not allowed
nList.add(0.5);
With generics, you will never get runtime ClassCastExceptions as long as you have code that compiles without warnings.
Upper Bounded Wildcards
What we want is a list whose exact element type is unknown.
- A List<Number> is a list whose element type is the concrete type Number - exactly.
- A List<? extends Number> is a list whose exact element type is unknown. It is Number or a subtype.
If we update our original example, and assign to a List<? extends Number>, the assignment now succeeds:
List<Integer> iList = new ArrayList<Integer>();
List<? extends Number> nList = iList;
Number n = nList.get(0);
nList.add(0.5); // Not allowed
We can get Numbers out of the list because no matter what the exact element type of the list is (Float, Integer, or Number), we can still assign it to Number.
We still can't insert floats into the list. This fails at compile time because we can't prove that this is safe. If we were to add a float into the list, it would violate the original type safety of iList - that it stores only Integers.
Wildcards give us more expressive power than is possible with arrays.
Why Use Wildcards
In this example, a wildcard is used to hide type information from the user of the API. Internally, the set is stored as CustomerImpl. To the user of the API, all they know is that they are getting a set from which they can read customers.
Wildcards are necessary here because you can't assign from a Set<CustomerImpl> to a Set<Customer>.
public class CustomerFactory {
private Set<CustomerImpl> _customers;
public Set<? extends Customer> getCustomers() {
return _customers;
}
}
Wildcards and Covariant Returns
Another common use for wildcards is with covariant returns. The same rules apply to covariant returns as assignment. If you want to return a more specific generic type in an overridden method, the declaring method must use wildcards:
public interface NumberGenerator {
public List<? extends Number> generate();
}
public class FibonacciGenerator extends NumberGenerator {
public List<Integer> generate() {
...
}
}
Published February 6, 2006 Reads 33,219
Copyright © 2006 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Jess Garms
Jess Garms works at BEA Systems.
More Stories By Tim Hanson
Tim Hanson is the Javelin compiler architect at BEA Systems. Tim developed much of BEA's Java compiler - one of the earliest 1.5-compliant implementations. He has written numerous other compilers, including a CORBA/IDL compiler while at IBM, and an XQuery compiler.
![]() |
SYS-CON Brazil News Desk 02/06/06 11:31:53 AM EST | |||
During the beta period for JDK 1.5, we worked on a 1.5 Java compiler for BEA's Java IDE. As we implemented various new features, people would begin exploiting them in new ways, some clever, some clearly candidates for a list of what not to do. The compiler itself used 1.5 features, so we gained direct experience in maintaining 1.5 code as well. |
||||
![]() |
SYS-CON India News Desk 02/06/06 10:49:34 AM EST | |||
During the beta period for JDK 1.5, we worked on a 1.5 Java compiler for BEA's Java IDE. As we implemented various new features, people would begin exploiting them in new ways, some clever, some clearly candidates for a list of what not to do. The compiler itself used 1.5 features, so we gained direct experience in maintaining 1.5 code as well. |
||||
- Kindle 2 vs Nook
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- Confessions of a Ulitzer Addict
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- It's the Java vs. C++ Shootout Revisited!
- Cloud Computing Can Revitalize Your Career as Software Developer
- IBM Could "Reinvent" Java: Mills
- Oracle & Cloud Computing: Exclusive Q&A with SVP Richard Sarwal
- A Brief History of Cloud Computing
- Kindle 2 vs Nook
- Cloud CEOs, CTOs & SVPs to Speak at 4th International Cloud Computing Expo
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- The Difference Between Web Hosting and Cloud Computing
- Cloud Computing Expo: Exclusive Q&A with Yahoo! SVP Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- My Thoughts on Ulitzer
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- The i-Technology Right Stuff
- JavaServer Faces (JSF) vs Struts
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- What's New in Eclipse?
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- i-Technology Predictions for 2007: Where's It All Headed?









































