0

I have a simple set of concrete classes that all extend the same interface.

I want to pass in an optional list of objects into a method, so my method signature looks roughly like this:

    void method(Optional<List<? extends AnInterface> arg);

When I create an argument using a concrete type, Concrete1, which implements AnInterface and use it in the method call:

    List<Concrete1> list = new ArrayList<>();
    Optional<List<Concrete1>> opt = Optional.of(list);

    ex.method(opt);

I get the following error:

'method(Optional<List<? extends AnInterface>>)' in 'GenericArgBoundsExample' cannot be applied to '(Optional<List>)'

Because Concrete1 implements AnInterface I would think the method should be applicable to the argument Optional<List>.

If I do the same thing without the Optional, "method(List<? extends AnInterface>)", there are no issues.

Is it possible to define the method in such a way that I can pass in this type of argument?

Below is a stripped down test class that I use to generate this error.

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

interface AnInterface {
    void aMethod();
}

class Concrete1 implements AnInterface {
    @Override
    public void aMethod() { /* Do nothing. */ }
}

class Concrete2 implements AnInterface {
    @Override
    public void aMethod() { /* Do nothing. */ }
}

public class GenericArgBoundsExample {

    public void takesAList(List<? extends AnInterface> arg) { /* Do nothing. */ }

    public void takesAnOptional(Optional<? extends AnInterface> arg) { /* Do nothing. */ }

    public void takesAnOptionalList(Optional<List<? extends AnInterface>> arg) { /* Do nothing. */ }

    public static void main() {
        GenericArgBoundsExample ex = new GenericArgBoundsExample();

        List<Concrete1> listConcrete = new ArrayList<>();
        Optional<Concrete1> optConcrete = Optional.of(new Concrete1());
        Optional<List<Concrete1>> optListConcrete = Optional.of(listConcrete);

        // Ok
        ex.takesAList(listConcrete);

        // Ok
        ex.takesAnOptional(optConcrete);

        // Not Ok
        ex.takesAnOptionalList(optListConcrete);

        // Error message:
        // 'takesAnOptionalList(Optional<List<? extends AnInterface>>)' in
        // 'GenericArgBoundsExample' cannot be applied to '(Optional<List<Concrete1>>)'
    }
}
M. Krajnak
  • 97
  • 1
  • 9
  • Taking an optional as an argument is jank because we have overloading. Taking an optional list is even more jank because you can just pass an empty list. In any case, seems you don't understand wildcards. See the linked duplicate. You can fix it with the signature `public void takesAnOptionalList(Optional> arg)` – Michael Nov 14 '20 at 17:10
  • Yes that that solved my problem. And yes, there's definitely plenty more to learn here. The use of Optional is also pretty jank, but I wanted to post the question on the grounds I couldn't puzzle through the error message myself and didn't want to leave it that way. Cheers. – M. Krajnak Nov 14 '20 at 19:21

0 Answers0