11

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,127
  • 4
  • 13
  • 29

4 Answers4

10

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
  • 43,835
  • 9
  • 63
  • 92
  • 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 <: an="" as="" b="" be="" c="" cannot="" extends="" find="" follows="" for="" however="" i="" inclusive="" is="" it="" just="" reference="" relation="" should="" since="" subtype="" the="" this.="" 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 <: an="" and="" be="" breaks="" code="" correct="" could="" course="" how="" however="" http:="" i="" if="" in="" inclusive="" is="" it="" me="" not="" object="" of="" point="" provided="" relation="" see="" somehow.="" still="" subtype="" sure="" tells="" that="" the="" type-system="" where="" why="" wrong.="" yet.="" you="" your=""> – 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 can="" capture.="" is="" reason="" that="" we="" wildcard="" with="">`, 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 a="" fine="" is="" null="" so="" the="" type=""> – 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
  • 15,975
  • 10
  • 85
  • 128
1

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

Alex DiCarlo
  • 4,793
  • 17
  • 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
  • 389,931
  • 88
  • 552
  • 692