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();
source to share
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)
source to share
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.
source to share