Reputation: 492
If a method is defined as:
<T> List<T> transform(List<T> list)
What does the first T add? As it is essentially the same as:
List<T> transform(List<T> list)
Upvotes: 0
Views: 957
Reputation: 140484
<T> List<T> transform(List<T> list)
As it is essentially the same as:
List<T> transform(List<T> list)
It's not.
In the second case, T
has to have been defined on the containing class:
class GenericClass<T> {
List<T> transform(List<T> list) { ... }
}
and you can then only pass in/get back a list of the same element type as the class:
GenericClass<String> genericClass = new GenericClass<>();
List<String> stringList = genericClass.transform(Arrays.asList("")); // OK.
List<Integer> intList = genericClass.transform(Arrays.asList(0)); // Error!
However, with the first form, the T
isn't defined on the class, so it can be different on each invocation:
class NonGenericClass {
<T> List<T> transform(List<T> list) { ... }
}
NonGenericClass nonGenericClass = new NonGenericClass();
List<String> stringList = nonGenericClass.transform(Arrays.asList("")); // OK.
List<Integer> intList = nonGenericClass.transform(Arrays.asList(0)); // OK.
Upvotes: 2
Reputation: 40062
As was already said, the following are essentially identical.
<T> List<T> transform(List<T> list)
List<T> transform(List<T> list)
But the former also allows one to further constrain T. For example you can do
<T extends Foo> List<T> transform(List<T> list) {
...
}
You can only pass a List<T>
if T subclasses Foo.
Upvotes: 0
Reputation: 44200
<T>
is the definition. You need to define generic type parameters before you use them, just like you must define variables before you use them.
Remember, T
is just a naming convention. That identifier can be anything. It could be <F>
or <Foo>
.
Suppose they implemented it how you suggest, and the compiler just infers any missing type to be a generic type parameter. Suppose I have a custom class Foo
which I forgot to import.
List<Foo> transform(List<Foo> list)
The compiler would say "Ok, I don't know what Foo is, so let's just assume it's a generic parameter". Your method then compiles just fine, when you would much prefer that the compiler had caught that mistake.
Or maybe you think T
should be a special case. You would then be taking something that's currently just a convention and making that a special part of the language. You'd have to deal with the possibility of someone creating a real class called T
.
So explicit declarations have their uses, even if they may seem verbose sometimes.
Upvotes: 4
Reputation: 103244
It is not the same at all.
The <T>
declares the variable, the rest is the use of the variable. This straight up fails to compile:
public class Example {
public List<T> transform(List<T> foo) {}
}
try it.
In case this is what you have:
public class Example<T> {
public <T> List<T> transform(List<T> foo) {}
}
Then you have 2 unrelated type variables, both unfortunately named T
, which is extremely confusing; I strongly suggest you don't do that (the class has defined a and then the method defines its own T, ensuring that all uses of T in that method declaration are assumed to be the defined on the method; the defined by the class is no longer accessible; it has been 'shadowed'. It is in that sense equivalent to this:
public class Example {
int x;
public void foo(int x) { }
}
The int x
of foo is utterly unrelated to the int x;
field, but because they have the same name, you have made it impossible to refer to the field named x
. At least for this there's an escape (this.x
still refers to the field) - no such luxury with generics, so, do not shadow variables like this.
It is somewhat unlikely you want a type var on the method at all if you have this code; but if you really do, don't use T, but use anything else:
public class Foo<T> {
public <Y> List<Y> transform(List<Y> foo) {}
}
Upvotes: 2
Reputation: 262714
The difference is the scope of T
. It can be defined on the class level or for each individual method.
List<T> transform(List<T> list)
This one returns and accepts List<T>
where T
is the same for all methods.
<T> List<T> transform(List<T> list)
This method has its own T
unrelated to the generic type of its class (if any).
Upvotes: 5