9

To my understanding, <? extends Object> and <?> are same.

However, when I run the following code <? extends Object> does not get compiled and is working as expected but <?> is getting compiled successfully.

public class Test1 
{
    interface I1 
    {
    }

    interface I2<T extends I1> extends Comparable<I2<?>> 
    {
        Comparator<I2<? extends I1>> A = null;
        //Comparator<I2<? extends Object>> B = A; // expected compilation fail
        Comparator<I2<?>> B = A; // compiling successfully.This shouldn't get compile
    }
}

Can some one help me understand this behavior.

T-Bag
  • 10,916
  • 3
  • 54
  • 118
  • @ajb- My problem is statement 2 is getting compiled, though it should not be.Please check my code – T-Bag Jul 10 '17 at 04:01
  • Why shouldn't statement 2 be compiled? At least from an intuitive look at polymorphism, an `I2` of *something* extends `I1` can be called an `I2` of *something*. (In contrast, an `I2` of *something* extends `I1` can only be called an `I2` of *something* extends `Object` because we know that `I1` must be a subclass of `Object`, which is a conclusion I'm guessing the java compiler isn't willing to jump to.) – Mshnik Jul 10 '17 at 04:30
  • "Comparator> B = A" does not compile for me: "Type mismatch: cannot convert from Comparator> to Comparator>" – bichito Jul 10 '17 at 04:38
  • @efekctive-- That is correct , compilation failure is expected but why statement two is getting compiled ??? – T-Bag Jul 10 '17 at 04:39
  • I am counting statement 2 as the one commented out. Unless you are counting zero based :-} – bichito Jul 10 '17 at 04:40
  • @efekctive- Ok, statement 2 is the one that is not getting compiled and it is fine and is expected . My question is why does statement 1 getting compiled ? – T-Bag Jul 10 '17 at 04:42
  • 1
    No it is not duplicate . Please read the question carefully. – T-Bag Jul 10 '17 at 06:11
  • @user1803551-- Have you heard of term generics in java ????? If so please read the question again . Don't use powers like this!!!!! – T-Bag Jul 10 '17 at 06:15
  • PLease refer the link it mya help https://stackoverflow.com/questions/8055389/whats-the-difference-between-and-extends-object-in-java-generics – Zia Jul 10 '17 at 06:31
  • 1
    @Zia-- I know the difference very well. If you check my question then you will come to know what i want to ask here – T-Bag Jul 10 '17 at 06:37
  • @Joker please do not over-react. It is a community-managed site. If you think other has mis-understood your question, you can simply explain briefly how it is different from an existing question. – Adrian Shum Jul 10 '17 at 09:59
  • @AdrianShum-- I am not able to understand what part of this question is same with the duplicate you have mentioned. I am not looking for difference here. – T-Bag Jul 10 '17 at 10:08
  • Generics aren't polymorph ([Is List a subclass of List? Why aren't Java's generics implicitly polymorphic?](//stackoverflow.com/q/2745265)) and you should know that since you pretend you know generics. – Tom Jul 10 '17 at 10:15
  • @Tom- Let some big guys answer this , what you are saying every one knows that. Or if you think it is a answer then please share it as a answer. – T-Bag Jul 10 '17 at 10:20
  • You obviously don't know that or this question wouldn't exist. You could also try to read the suggested link and try to think about it and avoid pretending you know what you're talking about. And I obviously can't write an answer, because this question is closed. – Tom Jul 10 '17 at 10:32
  • 2
    Read the *second* answer on the duplicate question--it's, honestly, better than the first answer--and explains why this question is indeed a duplicate of that question. – dcsohl Jul 10 '17 at 14:18
  • @ShowStopper well, as dcsohl has mentioned, if you read carefully in the linked question, 2nd answer should have mostly answered your question. if you are looking for something else, I guess you need to be clearer on your question as it is questioners' responsibility to ask clearly – Adrian Shum Jul 11 '17 at 01:39
  • And, my personal advise: you can clean up your question a bit. You don't need `interface I2 extends Comparable> ` to demonstrate your problem, and it is worth to mention that `A extends Object> x = y` works while `B> x = y` failed (for which is something that cannot be fully explained by the duplicated question) – Adrian Shum Jul 11 '17 at 02:14

2 Answers2

7

This question is actually interesting but not asked clearly, which easily makes people think it is a duplicate.

First, an example which I think most people here should understand why it does not work:

class Foo<T> {}
class Bar<T> {}

class Parent{}

public class Test1 
{

    public static void main(String[] args) {
        Foo<Bar<? extends Parent>> a = null;
        Foo<Bar<? extends Object>> b = a;  // does not compile
        Foo<Bar<?>> c = a;                 // does not compile
    }
}

It is obvious: a Foo<Bar<?>> / Foo<Bar<? extends Object>> is not convertible to Foo<Bar<? extends Parent>> (To simply: just like you cannot assign List<Dog> to List<Animal> reference.)


However, in the question you can see the case of Comparator<I2<?>> B = A; does compile, which is contradict with what we see above.

The difference, as specified in my example will be:

class Foo<T> {}
class Bar<T extends Parent> {}

class Parent{}

public class Test1 
{

    public static void main(String[] args) {
        Foo<Bar<? extends Parent>> a = null;
        Foo<Bar<? extends Object>> b = a;  // does not compile
        Foo<Bar<?>> c = a;                 // COMPILE!!
    }
}

By changing class Bar<T> to class Bar<T extends Parent> created the difference. It is a pity that I still cannot find the JLS section that is responsible on this, but I believe it when you declare a generic class with bound in type parameter, the bound is implicitly carried to any wildcard you use against that.

Therefore, the example become:

class Foo<T> {}
class Bar<T extends Parent> {}

class Parent{}

public class Test1 
{

    public static void main(String[] args) {
        Foo<Bar<? extends Parent>> a = null;
        //...
        Foo<Bar<? extends Parent>> c = a;
    }
}

which explain why this compile.

(Sorry I cannot find evidence this is how the language is designed. It will be great if someone can find in JLS for this)

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
  • 1
    The closest I can find in JLS is (Java 7, section 4.5.1): `The relationship of wildcards to established type theory is an interesting one, which we briefly allude to here. Wildcards are a restricted form of existential types. Given a generic type declaration G, G> is roughly analogous to Some X <: B. G. ` – Adrian Shum Jul 11 '17 at 03:12
  • @Adrian-- finally someone understands this... thanks a lot for your analysis.. :) – T-Bag Jul 11 '17 at 05:39
2

Let me explain to you with a simple example:

List<String> list = new ArrayList<>();
List<Object> listObject = new ArrayList<>();
listObject = list;

Here, Object class is Super class of String class, nevertheless you will receive the below specified compilation error because you have specified your list to accept a specific type of Objects only i.e. 'Object' for listObject and 'String' to list.

Type mismatch: cannot convert from List<String> to List<Object>

On similar explanation below,

//Comparator<I2<? extends Object>> B = A; // expected compilation fail

The above line is failing because you are trying to typecast two non-matching types:

Type mismatch: cannot convert from Comparator<Test1.I2<? extends Test1.I1>> to Comparator<Test1.I2<? extends Object>>
T-Bag
  • 10,916
  • 3
  • 54
  • 118
GaurZilla
  • 371
  • 4
  • 13