Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic inference in constructors

Tags:

java

generics

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?

like image 350
Jeffrey Avatar asked Aug 28 '11 20:08

Jeffrey


2 Answers

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");
like image 170
Bohemian Avatar answered Sep 27 '22 23:09

Bohemian


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 the Map<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.

like image 28
Paul Bellora Avatar answered Sep 28 '22 01:09

Paul Bellora