Reputation: 1661
I have an abstract class named BaseCode
and 2 concrete classes named Location
and Department
:
public abstract class BaseCode {
private Integer id;
...
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
...
}
public class Location extends BaseCode {
...
}
public class Department extends BaseCode {
...
}
I have an abstract class named BaseCodeCache
and 2 concrete classes named LocationCache
and DepartmentCache
. LocationCache
and DepartmentCache
will be using Singleton
.
public abstract class BaseCodeCache {
...
}
public class LocationCache extends BaseCodeCache {
...
}
public class DepartmentCache extends BaseCodeCache {
...
}
BaseCodeCache
, I want to have a java.util.Map
whose value can
be any type of BaseCode
i.e. Location
objects or Department
objects.LocationCache
, I want the java.util.Map
to store Location
objects. DepartmentCache
, I want the java.util.Map
to store Department
objects. To accomplish this, I put this code in BaseCodeCache
:
private Map<Integer, BaseCode> idMap = new HashMap<Integer, BaseCode>();
java.util.Map
.
To accomplish this, I put this code in BaseCodeCache
:
public void add(BaseCode baseCode) {
if (baseCode != null) {
idMap.put(baseCode.getId(), baseCode);
}
}
This is how I would use it for Location
:
Location location = new Location(); ...
LocationCache.getInstance().add(location);
This is how I would use it for Department
:
Department department = new Department(); ...
DepartmentCache.getInstance().add(department);
java.util.Map
as
a java.util.List
. LocationCache
this method should return List<Location>
. DepartmentCache
this method should return List<Department>
. Thats where I am stuck. I want to create this method in BaseCodeCache
but when this method is called via LocationCache
then it returns List<Location>
and when this same method is called via DepartmentCache
then it returns List<Department>
. Is it possible?
I put this code in BaseCodeCache
:
public List<BaseCode> getList() {
return new ArrayList<BaseCode>(idMap.values());
}
But the above code returns List<BaseCode>
. When I would call it this way:
List<Location> allLocations = LocationCache.getInstance().getList();
Then java will not let it compile and give this error message:
Type mismatch: cannot convert from
List<BaseCode>
toList<Location>
I can get it fixed by getting List<BaseCode>
and then converting it to List<Location>
by looping but thats does not look right.
Can it be done?
Upvotes: 3
Views: 1365
Reputation: 97130
Implement using generics as follows:
public abstract class BaseCodeCache<T extends BaseCode> {
private Map<Integer, T> idMap = new HashMap<>();
public void add(T baseCode) {
if (baseCode != null) {
idMap.put(baseCode.getId(), baseCode);
}
}
public List<T> getList() {
return new ArrayList<>(idMap.values());
}
}
public class LocationCache extends BaseCodeCache<Location> {}
public class DepartmentCache extends BaseCodeCache<Department> {}
This will then enable you to do the following without any compilation errors:
LocationCache locationCache = new LocationCache();
locationCache.add(new Location());
List<Location> locations = locationCache.getList();
Even better, you will get compilation errors if you try to add or retrieve the wrong type of objects:
locationCache.add(new Department()); // won't compile
List<Department> departments = locationCache.getList(); // won't compile
Upvotes: 4