14

Possible Duplicate:
What’s the difference between <?> and <? extends Object> in Java Generics?

I found that List<?>and List<? extends Object> act in the same way. As for me, there are no difference between them. If I am not right, can you explain me the difference?

import java.util.ArrayList;
import java.util.List;

public class TestClass {

static void func1(List<?> o, Object s) {
    o.add(null); // only null
    o.add(s); // wrong
    o.get(0);  // OK
}

static void func2(List<? extends Object> o, Object s) {
    o.add(null); // only null
    o.add(s); // wrong
    o.get(0); // OK
}

public static void main(String[] args) {
    func1(new ArrayList<String>(), new Integer(1));
    func2(new ArrayList<String>(), new Integer(1));

    List<? extends Object> list1 = new ArrayList<Object>();
    List<?> list2 = new ArrayList<Object>();

    List<? extends Object> list3 = new ArrayList<String>();
    List<?> list4 = new ArrayList<String>();
}
}
Community
  • 1
  • 1
Anton Kasianchuk
  • 1,177
  • 5
  • 13
  • 31

4 Answers4

13

It is complicated...

For any type variable T, the spec says http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4

Every type variable ... has a bound. If no bound is declared for a type variable, Object is assumed.

One would think that it's true for wildcard too, and ? should just be a shorthand for ? extends Object.

Yet searching through the spec, there is no evidence at all that a wildcard must have an upper bound (or lower bound). The "unbounded" ? is treated consistently distinctly from bounded wildcards.

We could deduce from subtyping rules, that List<?> and List<? extends Object> are subtypes of each other, i.e., they are basically the same type. (The deduction depends on the fact that E in interface List<E> has an implicit upper bound Object; but the rules do not require bounds on wildcards)

Nevertheless the spec treats the two differently. For example http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7 List<?> is a reifiable type, but List<? extends Object> is not, which means

    // ok
    List<?>[] xx = {};
    // fail
    List<? extends Object>[] yy = {};

    // ok
    boolean b1 = (y instanceof List<?>);
    // fail
    boolean b2 = (y instanceof List<? extends Object>);

I don't understand why though. It seems perfectly fine to say a wildcard must have an upper bound and a lower bound, default to Object and null type.

irreputable
  • 44,725
  • 9
  • 65
  • 93
  • But, there is this `Given a generic type declaration G, G> is roughly analogous to Some X <: B. G.` under 4.5.1. – nullpotent Jan 15 '13 at 22:38
  • @iccthedral - applied to the `List` case, `List> is roughly analogous to List for some X<:Object` – irreputable Jan 15 '13 at 23:23
  • 1
    Well, yes. That's my point. `X <: B` should (?) be an inclusive subtype relation, however I cannot find the reference for this. It just follows since `T extends C` is inclusive as well. – nullpotent Jan 16 '13 at 00:05
  • Okay, I've found it. Maybe I wasn't clear in my previous comment; my interpretation is that there exists `X` such that `X <: Object` where `<:` is an inclusive subtype relation (And http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.10 tells it is). And of course `X = Object`. Correct me if I'm wrong. However, I still see your point in code you provided, could be that it breaks the type-system somehow. I'm not sure how and why yet. – nullpotent Jan 16 '13 at 00:19
  • @iccthedral of course `List> is not List where X=Object`. But whenever an object of type `List>` is used, we know it is a `List` for some definite yet unknown `X<:Object`. That is wildcard capture. We can reason with `List`, e.g. `get()` return type is `X`, which is a subtype of `Object`, so `get()` can be assigned to `Object`; `add()` argument type is X, for any `A a`, we cannot do `add(a)`, since we don't known if `A<:X`. (unless A is the null type, so `add(null)` is fine) – irreputable Jan 16 '13 at 00:40
  • +1 Nice JLS detective work :) – Marko Topolnik Jan 16 '13 at 06:54
  • If I caught anyone writing code that depends on the difference between `List>` and `List extends Object>`, that person would be in trouble. – barfuin Jan 16 '13 at 10:04
  • [JLS8](http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1) - The wildcard ? extends Object is equivalent to the unbounded wildcard ?. – ZhongYu Jun 13 '15 at 18:09
  • javac8 - allows `List extends Object>[]`, but not `instanceof List extends Object>` – ZhongYu Jun 13 '15 at 18:09
  • guys, is it fair to say that `boolean b2` above example now compiles (tested with JDK18) and all became logical now? – Max May 06 '22 at 04:21
1

Both are the same because all objects in Java extend Object. I would prefer List<?> because it's more concise.

barfuin
  • 16,865
  • 10
  • 85
  • 132
1

Similar to how MyClass extends Object for every class List<? extends Object> is the same as List<?>.

Alex DiCarlo
  • 4,851
  • 18
  • 34
0

Although I'm plagiarising Marko, for which I apologise, his comment is the correct answer.

There is no difference, because implicitly every type extends Object.

Bohemian
  • 412,405
  • 93
  • 575
  • 722