Browsing through Guava libraries I saw this weird signature on a readLines method from Files class:
public static <T> T readLines(File file,
Charset charset,
LineProcessor<T> callback)
I know a little bit about generics in java, but this baffled me.
What does the double T mean here? And why is the first one in angled bracke开发者_如何转开发ts?
UPDATE: Thanks for the answers. I am still not clear as to why I should use a T inside the brackets. Why for example can't it just be:
public static <> T readLines()
or
pulibc static <K> T readLines()
Or does the java syntax dictate that the SAME letter must be used?
Now this is even wierder:
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
how can a method have a generic-return type and be void?
It's a generic method -- the T
is called a type parameter, and can represent any type. So if I have a method with this signature:
public <T> T foo(T[] bar)
I can call it on any array, and it will return a single object of the same type. If I pass it a String array, I'll get back a String, and so on. More information in the Sun tutorials for "generic methods".
Edit: In answer to your updated question, bear in mind that the first <T>
isn't part of the return type: it's just an indicator that T
is a type parameter. So look at the example you quoted:
static <T> void fromArrayToCollection(T[] a, Collection<T> c)
That just means that fromArrayToCollection
will accept any array and any collection, but that they must be an array and collection of the same type. So you can pass in a String[]
and a Collection<String>
, or an Integer[]
and a Collection<Integer>
, but not a String[]
and a Collection<Integer>
. No matter what type you put in for T
, the method returns nothing.
The first T inside the angle brackets mean that the method itself is generic. The second T is the return type. T can be any type within its bounds. In this case, T has no bounds.
T will be determined at the call site, and in this case, inferred from the LineProcessor<T> parameter.
I am still not clear as to why I should use a T inside the brackets. Why for example can't it just be:
public static <> T readLines()
or
public static <K> T readLines()
Or does the java syntax dictate that the SAME letter must be used?
The <T>
or <K>
is the type parameter. If you write <K> T
, then the T isn't a type parameter - rather, you're using the specific class T
. This won't work if you don't have a class that's literally named T
in scope.
Now this is even wierder:
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
how can a method have a generic-return type and be void?
It doesn't; the <T>
is not a "generic return type", it's just the type parameter to the method. You're saying that the method is generic, and T
is the type parameter. The return type of the method is void
.
Instead of being generic at class level only the method readLines uses generics.
- The first
<T>
declares the generic types used by the method - The following T is the return type.
The first one uses the same syntax as a generic class to declare the generic types. Instead you could write
class Generic <T>
{
public static T readLines(File file,
Charset charset,
LineProcessor<T> callback)
}
This however would make all instances of the class generic.
Extended Example:
public static <ElementType,ListType extends List<ElementType>> ListType add(ListType list,ElementType elem)
{
list.add(elem);
return list;
}
ArrayList<String> = add(add(new ArrayList<String>(),"Hello"),"World");
The method adds a given Element to a List and returns the List.
The method uses two generic Types one for the elements of the list and one for the list itself.
The names used are nothing special, using a T for a generic type is like using i for an integer.
- ElementType is the name used for the generic Type of the elements (any valid variable name / identifier could be used)
- ListType is the name for the generic list Type, the classes used have to extend/implement List for the ElementType.
The example calls the method with:
- ElementType = String
- ListType = ArrayList
which would result in
public static ArrayList<String> add(ArrayList<String> list, String elem)
Bloat end :-)
This is a generic method.
Actually there are three Ts, the third on LineProcessor<T>
specifies T when you use the method.
精彩评论