If I have a class Foo
:
public class Foo<T> {
public Foo(T t) {
//do something
}
public static <E> void bar(E e) {
//do something
}
}
Why does Foo.bar("String");
infer that E
is a String (and therefore not throw a compiler warning) but new Foo("String");
not infer that T
is a String?
Because the constructor can be considered a special instance method, it is not typed - it gets its type from the class name (with a type parameter),eg Foo<String>
. ie the constructor is not defined as:
public <T> Foo(T t) ...
nor can it be. Doing so would hide the generic type of the class (and you'll get a warning)
The static method however is typed. FYI, the generic-parameter-less call, once the type is inferred, is equivalent to:
Foo.<String>bar("String");
When Java implemented generics, it was decided that a generic class instantiated without type parameters would always return a raw-type. This differs from generic methods missing type parameters, which the compiler tries to infer the type of. From the Java Tutorials:
Generally, the Java compiler can infer the type parameters of a generic method call. Consequently, in most cases, you do not have to specify them.
But when discussion turns to constructors:
Note that to take advantage of automatic type inference during generic class instantiation, you must specify the diamond. In the following example, the compiler generates an unchecked conversion warning because the HashMap() constructor refers to the
HashMap
raw type, not theMap<String, List<String>>
type:
Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning
source: http://download.oracle.com/javase/tutorial/java/generics/gentypeinference.html
This remains the same in Java 7, however they tried to make it less repetitive by supporting diamond syntax. For example, Foo<String> foo = new Foo<>("String")
. See this section of the same article.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With