Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of generic wildcard instead of interface

If you wanted to store an array of objects of type MyInterface, are the following both acceptable and if so when would you use the second form over the first?

i) Using only an interface:-

List<MyInterface> mylist = new ArrayList<MyInterface>();

ii) Using a generic wildcard:-

List<? extends MyInterface> mylist = new ArrayList<? extends MyInterface>();

Edit:

As the answers so far have pointed out, number ii won't compile. What is the difference between i and a case iii where :-

iii) Using a generic wildcard only in the reference:-

List<? extends MyInterface> mylist = new ArrayList<MyInterface>();
like image 311
Martin Avatar asked Apr 24 '11 15:04

Martin


People also ask

What is the use of wildcard in generics?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).

Can we use generic in interface?

8. Java Generic Classes and Subtyping. We can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.

What is the use of generic interface in Java?

Generics make a class, interface and, method, consider all (reference) types that are given dynamically as parameters. This ensures type safety. Generic class parameters are specified in angle brackets “<>” after the class name as of the instance variable.

Can a non-generic class implement a generic interface?

It is possible to create a non-generic class that implements a generic interface, provided that the type parameters are provided.


2 Answers

Second one won't compile. Imagine:

A implements MyInterface
B implements MyInterface

Then the following would match your second expression, but won't compile:

// incorrect
List<A> mylist = new ArrayList<B>();

Correction: Wrong one too:

List<? extends MyInterface> mylist = new ArrayList<MyInterface>();

It is right in a sense it does compile, but you cannot add any subclasses of MyInterface to it. Confusing, but correct -- after I read the explanation. Same reason: wildcard can be viewed for example as:

// I know this is not compileable; this is internal compiler "thinking".
// Read it as "somewhere someone may instantiate an ArrayList<A> and pass 
// it down to us; but we cannot accept it as something that could be 
// potentially used as List<B>"
List<A> mylist = new ArrayList<MyInterface>();

So this won't work:

mylist.add(b);

and vice versa. Compiler refuses to do those potentially incorrect operations.

The option which allows you to add any subclass of MyInterface to mylist is:

List<MyInterface> mylist = new ArrayList<MyInterface>();
like image 190
Vladimir Dyuzhev Avatar answered Oct 13 '22 00:10

Vladimir Dyuzhev


If you would like to store the ojects of type MyInterface the better (and compilable) approach would be -

List<MyInterface> mylist = new ArrayList<MyInterface>();

But if you would like to use in the method parameter then you can use option 2 (bounded wildcard type) for API flexibility.

public void someMethod(List<? extends MyInterface> myInterfaces);

EDIT:
The above code will give the more flexibility API because Generic types are invariant, so if you have -

public class A implements MyInterface {
  // some implementation 
}

and if someMethod has a parameter type List<MyInterface> then it won't be able to take the List<A>, this forces API users to create List with type MyInterface on the other side -
List<? extends MyInterface> will allow to pass List<A> to someMethod.. client usually has a List<ActualObject> so it's more flexible to provide a parameter which will take any implementation of MyInterface

At the same time do not use wildcard types as return types like

public List<? extends MyInterface> someMethod();

If the user of a class has to think about wildcard types, there is probably something wrong with the class’s API.

like image 30
Premraj Avatar answered Oct 12 '22 23:10

Premraj