Unbounded wildcards in Java
Asked Answered
B

6

20

Is there ever a difference between an unbounded wildcard e.g. <?> and a bounded wildcard whose bound is Object, e.g. <? extends Object>?

I recall reading somewhere that there was a difference in the early drafts of generics, but cannot find that source anymore.

Book answered 6/1, 2010 at 20:33 Comment(0)
A
20

As a point of pedntry, there is a difference if the class/interface/constructor/method declares a bound (other than extends Object).

interface Donkey<T extends Thing> { }

...
    Donkey<? extends Object> foo; // FAIL
Apostrophize answered 7/1, 2010 at 1:3 Comment(3)
Wow! Missed that completely.Book
the example compiles in javac 7Mannikin
@Mannikin Presumably that's a bug.Apostrophize
B
33

From a practical point to most people, <? extends Object> is the same as <?>, like everyone have suggested here.

However, they differ in two very minor and subtle points:

  1. The JVMS (Java Virtual Machine Specification) has a special specification for the unbounded wildcards, as ClassFileFormat-Java5 specifies that unbounded wildcard gets encoded as *, while encodes a Object-bounded wildcard as +Ljava/lang/Object;. Such change would leak through any library that analyzes the bytecode. Compiler writers would need to deal with this issue too. From revisions to "The class File Format"

  2. From reifiablity standpoint, those are different. JLS 4.6 and 4.7 codify List<?> as a reifiable type, but List<? extends Object> as a erasured type. Any library writer adding .isReifiable() (e.g. mjc lib) needs to account for that, to adhere to the JLS terminology. From JLS 4.6 and 4.7.

Book answered 6/1, 2010 at 21:28 Comment(0)
A
20

As a point of pedntry, there is a difference if the class/interface/constructor/method declares a bound (other than extends Object).

interface Donkey<T extends Thing> { }

...
    Donkey<? extends Object> foo; // FAIL
Apostrophize answered 7/1, 2010 at 1:3 Comment(3)
Wow! Missed that completely.Book
the example compiles in javac 7Mannikin
@Mannikin Presumably that's a bug.Apostrophize
P
4

From experimentation it seems that, for example, List<?> and List<? extends Object> are assignment-compatible both ways, and a method that has a signature using one of them can be overridden with a signature using the other. e.g.,

import java.util.List;

class WildcardTest<T> {
    public void foo(List<? extends T> bar) {}
}

class WildcardTest2 extends WildcardTest<Object> {
    @Override
    public void foo(List<?> bar) {super.foo(bar);}
}
Puerility answered 6/1, 2010 at 20:44 Comment(0)
M
2

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.

But the spec treats them separately nevertheless. 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.

Mannikin answered 15/1, 2013 at 22:23 Comment(2)
JLS8 - The wildcard ? extends Object is equivalent to the unbounded wildcard ?.Ornie
javac8 - allows List<? extends Object>[], but not instanceof List<? extends Object>Ornie
B
-1

Everything in java with the exception of primitives extend Object, so no, there would be no difference. Autoboxing allows the use of primitives so it could be said everything in java is an object.

Bale answered 6/1, 2010 at 20:38 Comment(0)
T
-1

<? extends Object> is EXACTLY the same as <?>. I'm sorry I don't have a reference handy, but ... it is. :)

EDIT: of course, I was only thinking from a particular perspective when I said that. Ignore my answer (which was quite correctly downvoted) and see the higher-rated answers for the real story.

Tulatulip answered 6/1, 2010 at 21:4 Comment(2)
Hey Kevin, good bumping into you. Thanks for looking into the Executors2 thing, much appreciated. :-) Also, feel free to look at my revised entry to "A very average puzzle"; I'd be keen to see what the "official" answer is, and whether my approach is considered "cheating". :-PPuerility
Oh, I can't, because apparently my post was deleted.Tulatulip

© 2022 - 2024 — McMap. All rights reserved.