Pergunta

According erasure concept I thought that

List and List<Object> are indentically but I noticed that

List<String> strList = new ArrayList<String>();  
        List<Object> objList = strList; //error
        List objList = strList; //valid construction
        List<?> objList = strList; //valid construction
Foi útil?

Solução

  • List<?> is a list with an unknown type. You cannot insert there because you cannot know what type you would be allowed to insert. It has a generic type (or not) but there is no way you can know it. If you get to insert something (typecasting the list first) you may be violating something so you should not.

  • A List<Object> is a list where you can insert any object and when you get an item you only know (at first) that it is an object (and you already knew that).

  • List is only allowed to be backward compatible (I think). Before Java 5 there were no generics. Java need to allow typecast between List and List<Anything> so the legacy code may work with modern code.

Outras dicas

List<?> is generic (wildcard), which means that it accepts from String to anything, that's why

List<?> objList = strList; //valid construction

while List<String> is not a subtype of List<Object>(But String[] is in fact a subtype of Object[], that's one of the reasons why generics and arrays don't mix well). For Object

List<? extends Object> objList = strList; //valid construction

because String extends Object, here means anything extends to Object is accepted.

First explanation:

If you define a List of Objects, than you state, that this List can contain anything you want. (This is some additional information you provide.)

If you define a List of Strings, than this is NOT a List of anything. It is a List of Strings.

A List of Strings is not the same as a List of Objects.


Technical explanation:

Let's say you have a class like this:

class Machine<T> {
    void process(T input) {
        ...
    }
}

If you then create an instance: new Machine<String>(), than the compiler knows, that your new object is ment to process Strings. It will fail if you want to make it process a Number, an Array or anything else.

If you create a more general machine, but calling new Machine<Object>(), than the compiler knows, that Strings, Numbers, Arrays and any kind of stuff can be processed by that machine.

The compiler will not allow you to cast the specific String-Machine (new Machine<String>()) to a general Object-Machine (Machine<Object>), because this would allow you to let it process Numbers, Arrays, etc. for what it was not meant for.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top