0

I know it may have something to do with Generic and Covariant return types. But I can not make it through.

Given two classes where Apple extends Fruit.

public class TestReturnValue {
    public static Supplier<? extends Fruit> conFruitExt = Apple::new;
    public static Supplier<Fruit> conFruit = Apple::new;    // Compiles
    public static final Supplier<Fruit> supApple = supplyApple(); // Compile ERROR

    private static Supplier<Apple> supplyApple() {
        return Apple::new;
    }

    public static void main(String[] args) {
        Fruit fruitExt = conFruitExt.get();
        Fruit fruit = conFruit.get();

        System.out.println(fruitExt);
        System.out.println(fruit);
    }
}

What is the different between conFruitExt and conFruit? They both are constructor of Apple, and calling get() create apple instances.

Does the additional ? extends part of conFruitExt type make any difference?

Update1 2020/11/19

As suggestted answer says, question mark in generic by jonrsharpe, Supplier<Fruit> does not compile to Suppier<Apple>, so public static final Supplier<Fruit> supApple = TestReturnValue::supplyApple; does not compile.

But as method supplyApple()'s return value indicates Apple::new is type of Supplier<Apple>, why does public static Supplier<Fruit> conFruit = Apple::new compiles. Doesn't it assign a Supplier<Apple> instance to Supplier<Fruit>?

SuN
  • 421
  • 5
  • 11
  • Does this answer your question? [What does the question mark in Java generics' type parameter mean?](https://stackoverflow.com/questions/3009745/what-does-the-question-mark-in-java-generics-type-parameter-mean) – jonrsharpe Nov 18 '20 at 17:59
  • @jonrsharpe Not quite. Question description was updated for more details. – SuN Nov 19 '20 at 03:46
  • generics are [invariant](https://stackoverflow.com/questions/52224806/comparable-vs-extends-comparable/52225316#52225316), for one example. Even if `Apple` _is_ `Fruit`, a `Supplier` _is not_ `Supplier`. – Eugene Nov 19 '20 at 03:48
  • @Eugene So why does `Supplier conFruit = Apple::new` compiles? Isn't it something like `Supplier conFruit = Supplier`? – SuN Nov 19 '20 at 03:54
  • 1
    your edit does not compile either. I think you are confused yourself what the question is now – Eugene Nov 20 '20 at 02:30
  • @Eugene You are right. I fixed it with more errors. Orginally I think it's a question about Generics and Convariant. With your answer I realized it is mixed with * the type of method reference and lambda*. I fixed the description, so it seems reasonable. And I will rearrange the question to make it more clear. – SuN Nov 20 '20 at 06:16

1 Answers1

2

By doing this:

public static Supplier<Fruit> conFruit = Apple::new;

you are creating a poly expression in Apple::new. These are inferred by the compiler in the context of usage. Think about it: if I give you just Apple::new - can you tell me what that is? A Supplier? Or a Provider (may be such a functional interface exists), etc? Thus these types are concluded from the surrounding context in which are used. It's like the compiler did:

public static Supplier<Fruit> conFruit = (Supplier<Fruit>) () -> new Apple();

which is perfectly legal (this is not what happens, but to make it easier for you to understand).

In the other method you have told what the return type is, explicitly:

private static Supplier<Apple> supplyApple() {...}

it is a Supplier<Apple>. Since generics are invariant, the second assignment fails.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 1
    Which is “the second assignment”? The line `Supplier supApple = TestReturnValue::supplyApple` fails, because `supplyApple` returns a `Supplier` and a `Supplier` is not assignable to `Fruit`. Variance is not even involved. Perhaps, you fixed it in your mind to `Supplier supApple = supplyApple()` which would fail due to invariance, but that’s not what the OP wrote (and it’s not helpful that it is not the second assignment either). – Holger Nov 19 '20 at 08:39
  • @Holger good point, I somehow inferred that from the OP question, don't know why :/ – Eugene Nov 19 '20 at 16:19