tags:

views:

150

answers:

5

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 brackets?

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?

+6  A: 

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.

ILMTitan
+6  A: 

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.

Etaoin
Thanks, see update to my question
drozzy
A: 

This is a generic method.

Actually there are three Ts, the third on LineProcessor<T> specifies T when you use the method.

starblue
+2  A: 

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 :-)

josefx
Thanks, this makes it clearer... but why do i have to use a letter "T" inside the brackets as opposed to, say, letter "K" or "B" or none at all (i.e. just empty brackets).
drozzy
The letter T is only a name, the names between < and > only declare names for the generic types used. You could declare a method with 3 generic types like this public static <TypeA,AnOtherType,ExtraType> ExtraType someMethod(TypeA var1,AnOtherTypeB var2, ExtraType var3).
josefx
+1  A: 

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.

Jesper
This is the sentence I was looking for: "You're saying that the method is generic, and T is the type parameter." Thanks!
drozzy