Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generic type resolution

Tags:

java

generics

I have started to work with Java recently and still got confused when dealing with generic types. The following is a simplified scenario where I am having some problems.

I have a class wich holds a Map using a Class type as Key and an Collection of objects of that class:

public class GenericListInside {
    private Map<Class<?>, List<?>> mapping = new HashMap<>();

    public <T> void addListing(Class<T> clazz, List<T> object) {
        mapping.put(clazz, object);
    }
}

I can call addListing without problems:

GenericListInside gli = new GenericListInside();
List<Foo> list = new ArrayList<>(); 
//add something to list
gli.addListing(Foo.class, list); 

Now i decided to create a Class to provide a fluid interface. Something like:

with(Foo.class).use(list);

Then i came with:

public class FluidInserter<T> {
    Class<T> clazz;
    GenericListInside gli = new GenericListInside();

    public FluidInserter with (Class<T> clazz) {
        this.clazz = clazz;
        return this;
    }

    public <T> void use(List<T> list) {
        gli.addListing(clazz, list);
    }
}

But when I try to compile I get:

Error:(18, 12) java: method addListing in class util.GenericListInside cannot be applied to given types;
required: java.lang.Class,java.util.List
found: java.lang.Class,java.util.List
reason: inferred type does not conform to equality constraint(s)
inferred: T
equality constraints(s): T,T

This message is a little bit confusing... can anyone figure out what am I doing wrong?

like image 454
marcellorvalle Avatar asked Feb 10 '16 14:02

marcellorvalle


People also ask

What is Parameterizedtype in Java?

A parameterized type is an instantiation of a generic type with actual type arguments. A generic type is a reference type that has one or more type parameters. These type parameters are later replaced by type arguments when the generic type is instantiated (or declared ).

Does Java support type inference?

Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable.

Does Java have generic types?

Java Generics was introduced to deal with type-safe objects. It makes the code stable. Java Generics methods and classes, enables programmer with a single method declaration, a set of related methods, a set of related types.


2 Answers

The generic method of your fluid builder takes a generic method parameter, but that parameter is not the same as the type of your clazz field, despite the name overlap.

Just remove <T> from your method declaration, while leaving List<T> as parameter:

public void use(List<T> list) {
    gli.addListing(clazz, list);
}

Off-topic note: you don't want to return a raw typed FluidInserter in your with method. Change the return type to:

public FluidInserter<T> with (Class<T> clazz)
like image 100
Mena Avatar answered Oct 02 '22 07:10

Mena


The problem is with the definition of your use(List<T> list) method:

public <T> void use(List<T> list) {
    gli.addListing(clazz, list);
}

Here, you're hiding the class-scoped type-parameter T, by introducing a method-scoped type-parameter with the same name.

It should rather be:

public void use(List<T> list) {
    gli.addListing(clazz, list);
}

and it should compile just fine, as T is already defined on class level.

like image 43
Konstantin Yovkov Avatar answered Oct 02 '22 07:10

Konstantin Yovkov