Java generics - one impl class, multiple views

I have an interface defined below and implemented by a single MatchedAddressImpl class.

interface MatchedAddress extends HouseHelpData, StreetHelpData, TownHelpData

public class MatchedAddressDetails implements MatchedAddress

      

the client must be given different views (HouseHelpData or StreetHelpData or TownHelpData or MatchedAddress) of the same MatchedAddressImpl. So I have provided the below API for clients.

public List<MatchedAddress> matchedAddresses()
public List<? extends HouseHelpData> houseHelpData()
public List<? extends StreetHelpData> streetHelpData();
public List<TownHelpData> townHelpData();

      

the problem is the client needs to do something like below and I read in effective Java that return types should not contain wildcards as using the clinic looks ugly ... I appreciate if someone can help me improve the API , i want to remove masks from above methods ... thanks in advance

List<? extends StreetHelpData> streetHelpDataList = details.streetHelpData();

      

+2


source to share


2 answers


In most cases, correct use is simple List<StreetHelpData>

. For example, you could put objects like StreetHelpDataImpl

.

Wildcards are misleading in my opinion. Basically, List<? extends StreetHelpData>

this would mean: "This list contains elements of all a specific type, which is a subtype of StreetHelpData."

Wildcard example:

Consider:



class Animal {}
class Lion extends Animal {}
class Tiger extends Animal {}

      

The list List<? extends Animal>

contains only Lions

( List<Lion>

), Tigers

only ( List<Tiger>

), or both ( List<Animal>

). However, the list List<Animal>

can contain all sorts of Animals

- Lions

and / or Tigers

- all the time.

(Thanks to Tom Hawtin for his pointers)

+1


source


Why do you need wildcards in your API? Get rid of them.

I am guessing the reason you did this, you tried the following in your implementation:

public List<HouseHelpData> houseHelpData() {
    List<MatchedAddressDetails> results = new ArrayList<MatchedAddressDetails>();
    ... // populate it
    return results;
}

      

and you have a compiler error. The Java Generic Tutorial explains why the above is illegal - basically it should prevent you from inadvertently adding HouseHelpData

an incompatible implementation MatchedAddressDetails

to the list and then trying to access it (from the list down) as an instance MatchedAddressDetails

. However, you CAN :



public List<HouseHelpData> houseHelpData() {
    List<HouseHelpData> results = new ArrayList<HouseHelpData>();
    ...
    results.add(new MatchedAddressDetails());
    ...
    return results;
}

      

No wildcards required.

If that wasn't the reason for adding wildcards to the API, perhaps you can clarify your question and explain what it is.

+1


source







All Articles