-1

Say you have some class with type T:

class MyClass<T extends SomeOtherClass> {
    ....
}

Now, you want to store instances of this class into a collection, but you don't really care about the type. I would express this as following:

private final List<MyClass> entries = new ArrayList<>();

Is there any good reason/advantage to write the following instead?

private final List<MyClass<?>> entries = new ArrayList<>();

Or even:

private final List<MyClass<? extends SomeOtherClass> entries = new ArrayList<>();

I myself can only find a bad reason to do this: whenever the type definition of MyClass changes (for example addition of another type), you have to alter the List<MyClass<?>> or List<MyClass<? extends SomeOtherClass>> definitions all over your code as well.

update

To update my question:

Why isn't the compiler to be able to track the type(s) of MyClass when your write List<MyClass> (or even List<MyClass<? extends SomeOtherClass>>)? He knows that MyClass is defined as MyClass<T extends SomeOtherClass>, so why isn't he able/allowed to do that when you write List<MyClass>?

In other words, why is List<MyClass> not equal to List<MyClass<?>> (or even List<MyClass<? extends SomeOtherClass>>)? The compiler has all the information to make that conclusion himself, afaik.

  • 1
    Take at look at this great answer: http://stackoverflow.com/a/3009779/2215166 – christophetd Oct 23 '15 at 16:11
  • 2
    http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it Potentially relevant. Also the `? extends SomeOtherClass` is certainly useful as it provides compile-time errors about class incompatibility which saves on a lot of headaches if you really truly only want generics that implement a particular interface. – CollinD Oct 23 '15 at 16:11
  • 3
    Possible duplicate of [What does the question mark in Java generics' type parameter mean?](http://stackoverflow.com/questions/3009745/what-does-the-question-mark-in-java-generics-type-parameter-mean) – Joe Oct 23 '15 at 16:11
  • I added some extra info, as I don't that see that answered in the linked questions. –  Oct 23 '15 at 16:21
  • My question is not really about the meaning of `?`, but about the reason why it is necessary to use it in the first place. –  Oct 23 '15 at 16:23

3 Answers3

0

Your first declaration means, you are not giving any information about your generic data for the future reflection systems, could be used by plugins, which are written for your main program.

The second declaration tells them, that the field contains an Object generics.

The third one is the more specific, it means, that the reflection systems knows, what is this field about detailly.

gyurix
  • 1,106
  • 9
  • 23
0

The ? wildcard is useful when you don't need to refer to the type again and so you don't need to make a specific identifier.

Your first snippet starts with class MyClass<T extends SomeOtherClass>. This is necessary when T is important later on, perhaps to declare a field argument, or return type. For example:

class MyClass<T extends SomeOtherClass> {
    private final List<T> aListOfT;
    public T getSomething() {
        return this.aListOfT.get(0);
    }

Since MyClass is a generic type, all references to it should be qualified to avoid avoidable runtime errors. Thus when you declare List<MyClass> you get a compiler warning that you use the raw type MyClass. If you don't care at that location in the code what sort of type MyClass is qualified with, then you use the ? to tell the compiler that you don't care and let it track the type and check all operations for validity.

dsh
  • 12,037
  • 3
  • 33
  • 51
  • Why isn't the compiler to be able to track the type when your write `List`? He knows that `MyClass` is defined as `MyClass`, so why isn't he able/allowed to do that when you write `List`? –  Oct 23 '15 at 16:18
  • 1
    `MyClass` is incomplete . The compiler doesn't know what `T` is when you omit it. Much like `List` is a raw type. If you don't care what the list contains then you write `List>`. The compiler will show it as `capture-1-of-?` (or something similar) when it needs to show it in an error. And each `?` is its own type that is not compatible with the others. – dsh Oct 23 '15 at 17:58
0

Using the first type, java will assume that the generic type is Object. The reason for this is, that generics were introduced in version 1.5. Before then the collection-classes stored everything as an object. For compatibility reasons giving no generic parameter means that you are using object.

The second type simply says you don't know or don't care what type it is. This information is preserved when the code gets compiled. So other programmer who might use your code would know that you don't care.

Because of java's type-erasure, there is no difference between these two at runtime.

With the last form you say: I don't care what it is, but it has to be SomeOtherClass or a derivated type. Which is the same as:

List<MyClass<SomeOtherClass>>

You can also do it the other way around:

List<MyClass<? super SomeOtherClass>>

says that you don't care what type it is, unless it is a supertype of SomeOtherClass.

masinger
  • 775
  • 6
  • 13