Unbounded wildcards in Java

2019-01-11 01:15发布

问题:

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.

回答1:

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


回答2:

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.



回答3:

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);}
}


回答4:

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.



回答5:

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.



回答6:

<? 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.