简体   繁体   中英

Java ArrayList of ? extends Interface

I have a group of classes that all implement a validation interface which has the method isValid() . I want to put a group of objects--all of different classes--into an ArrayList, loop through them and call isValid() on each.

Here's my code

Email email = new email();
Address address = new Address();

ArrayList<? extends Validation> myValidationObjects = new ArrayList();

But when I try to do:

myValidationObjects.add(email);

I get:

The method add(capture#2-of ? extends Validation) in the type ArrayList is not applicable for the arguments (Email)

Both Email and Address implement Validation.

According to this document , I should be able to use extends for both interfaces and subclasses.

You can use:

List<Validation> myValidationObjects = new ArrayList<>();           // Java 7
List<Validation> myValidationObjects = new ArrayList<Validation>(); // pre Java 7

Now you can add any instance of a class that implements Validation to that list.

List<? extends Validation> myValidationObjects

Incorrect reading

" myValidationObjects is list of objects that extend Validation ."

Correct reading

" myValidationObjects can be a list of any type that extends Validation . For example, it could be a List<RangeValidation> or a List<RegexValidation> ."

Since there is no object you can legitimately add to both a List<RangeValidation> and a List<RegexValidation> , Java prevents you to call add on a variable of such type.

Your case is in fact the simpler one: you need the definite type List<Validation> .

The declaration ArrayList<? extends Validation> ArrayList<? extends Validation> means a list of an unknown class that extends Validation . Email is not compatible with this unknown class.

You can use ArrayList<Validation> for your list.

If a generic class's T is <? extends Foo> <? extends Foo> , then the only thing you can pass to a method that takes T is null -- not any subclass that extends Foo .

The reason is that List<? extends Validation> List<? extends Validation> doesn't mean "a list of things that extend Validation". You can get that with just List<Validation> . Instead, it means "a list of some type, such that that type extends Validation."

It's a subtle distinction, but basically the idea is that List<? extends T> List<? extends T> is a subtype of List<T> , and you therefore don't want to be able to insert anything into it. Think of this case:

List<FooValidation> foos = new ArrayList<>();
List<? extends Validation> validations = foos; // this is allowed
validations.add(new BarValidation()); // not allowed! this is your question
FooValidation foo = foos.get(0);

If the third line were allowed, then the last line would throw a ClassCastException.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM