ADOGCATFISH3333
ADOGCATFISH3333

Reputation: 31

Java generics - How to add non generic to a generic list

I'm attempting to create a method that will add elements from a defined list, into a generic list.

Here is the code:

private List<IEntity> entities = new ArrayList<IEntity>();

public <T extends IEntity> List<T> values(Class<T> type) {
    List<T> types = new ArrayList<T>();

    for (IEntity v : entities) {
        types.add(v); //Error
    }

    return types;
}

The sytax error occurs on types.add(v); with the error message (T) in List cannot be applied to (com.test.entities.IEntity).

Is there any way to do what I'm trying to do efficiently without having to cast?

Upvotes: 1

Views: 274

Answers (4)

Brian Goetz
Brian Goetz

Reputation: 95376

The compiler is giving you a type error because your program is not safe.

You have a List<T>. You don't know what T is, just that it extends IEntity. (Let's use Number as an example instead of IEntity, to make it more clear.) So you have a List of some kind of Number, maybe it's a List<Integer>, or maybe a List<Float>, you don't know. And you're trying to add a Number to it. But you have no reason to believe that this list can hold Number! A List<Integer> cannot hold an arbitrary Number, because you can't put Long or Float or Short into a List<Integer> -- Java generics are invariant.

So, basically your program is broken and the compiler is telling you so.

Upvotes: 9

waltron
waltron

Reputation: 151

If you want to make a generic class you could do something like this.

private class MyClass<T extends IEntity> {
    private List<T> entities;

    ...

    public List<T> values() {
        List<T> types = new ArrayList<>();

        for (T v : entities) {
            types.add(v); // All Good
        }
        return types;
    }
} 

interface IEntity { ... }

interface ISubEntity extends {...}

Then when you know you are using ISubEntity, you can instantiate as follows;

MyClass<ISubEntity> myClass = new MyClass<>(); 

Subsequent calls to values would then return a List typed for you.

Here is the formal doc online about generics.

Upvotes: 0

LowLevel
LowLevel

Reputation: 1095

Because you don't provide more information about the concrete structure of what you're going to do, it's difficult to offer a better solution.

interface Entity {} // In Java, unlike in .NET environment, interface names do not begin with "I". You write Entity or EntityInterface, sometimes also EntityInt

class EntityImpl {
    private final List<Entity> entities = new ArrayList<>();

    // List of T is undefined
    public <T extends Entity> List<T> getValues(Class<T> type) { // in Java it's important to write "get" for a getter-method before the property-name, if it's not a boolean-getter.
        List<T> types = new ArrayList<>();
        types.addAll((Collection<? extends T>) entities);
        return types;
    }
}

Upvotes: 0

define cindy const
define cindy const

Reputation: 632

You can't insert a IEntity to a list that holds subclasses of IEntity - T extends IEntity. You would need a list that holds super classes of IEntity to put an IEntity in it - T super IEntity.

Upvotes: 0

Related Questions