0

I have the following code snippet, at the first glance it should work, but I receive very interesting error:

'apply(capture<? extends Generic.MyClass>)' in 'java.util.function.Function' cannot be applied to '(capture<? extends Generic.MyClass>)'

This error occurs here: function.apply(wrapper.value);

What am I missing?

public class Generic {

    public static void main(String[] args) {
        Wrapper wrapper = new Wrapper<>(new MyClass());
    }

    private static void method(Wrapper<? extends MyClass> wrapper) {
        Function<? extends MyClass, String> function = (MyClass m) -> m.getClass().toString();
        function.apply(wrapper.value);
    }

    static class Wrapper<T extends MyClass> {
        private final T value;

        Wrapper(T value) {
            this.value = value;
        }
    }

    static class MyClass {

    }

}

Yan
  • 318
  • 2
  • 10

2 Answers2

4

Change the variable type to (*):

Function<MyClass, String>

? extends MyClass means that this function accepts a specific subclass of MyClass, but you just don't know which one.

Although the error message makes it look like the types are the same, they're not: each of the ? extends MyClass refers to a different (but specific) type.

The only thing you can safely pass to this function would be literal null.

The acronym PECS tells you that extends is used for producer methods (e.g. "wrapper produces value"). It is not used for consumer methods (e.g. "function accepts a T as a parameter"): that's what super is for.


(*) Or just use wrapper.value.getClass().toString();, and don't bother declaring the function.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
0

You could make the method generic:

public class Main {

    public static void main(String[] args) {
        Wrapper wrapper = new Wrapper<>(new MyClass());
    }

    private static <T extends MyClass> void method(Wrapper<T> wrapper) {
        Function<T, String> function = (T m) -> m.getClass().toString();
        function.apply(wrapper.value);
    }

    static class Wrapper<T extends MyClass> {
        private final T value;

        Wrapper(T value) {
            this.value = value;
        }
    }

    static class MyClass {

    }

}
keuleJ
  • 3,418
  • 4
  • 30
  • 51