泛型:如何在不进行强制类型转换的情况下获取Map的值

3

我有一个名为BaseCode的抽象类和两个具体类LocationDepartment:

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 {
   ...
}

我有一个抽象类名为BaseCodeCache和两个具体类名为LocationCacheDepartmentCacheLocationCacheDepartmentCache将使用Singleton

public abstract class BaseCodeCache {
   ...
}

public class LocationCache extends BaseCodeCache {
   ...
}

public class DepartmentCache extends BaseCodeCache {
   ...
}

在`BaseCodeCache`中,我想要有一个`java.util.Map`类型的映射表,其值可以是任何类型的`BaseCode`即`Location`对象或`Department`对象。在`LocationCache`中,我想要`java.util.Map`来存储`Location`对象。 在`DepartmentCache`中,我想要`java.util.Map`来存储`Department`对象。为了实现这个目标,我在`BaseCodeCache`中添加了以下代码:
private Map<Integer, BaseCode> idMap = new HashMap<Integer, BaseCode>();

  1. 我希望有一种方法来在java.util.Map中存储一个值。

为了达到这个目的,我在BaseCodeCache中添加了以下代码:

public void add(BaseCode baseCode) {
   if (baseCode != null) {
      idMap.put(baseCode.getId(), baseCode);
   }
}

以下是我如何使用它来处理位置(Location)的:

Location location = new Location(); ...
LocationCache.getInstance().add(location);

这是我在IT技术中使用Department的方法:
Department department = new Department(); ...
DepartmentCache.getInstance().add(department);

  1. 我希望有一种方法可以将 java.util.Map 中的所有值作为 java.util.List 返回。
    LocationCache 中,此方法应返回 List<Location>
    DepartmentCache 中,此方法应返回 List<Department>

这就是我卡住的地方。 我想在 BaseCodeCache 中创建此方法,但是当通过 LocationCache 调用此方法时,它返回 List<Location>,而当通过 DepartmentCache 调用相同的方法时,则返回 List<Department>这是否可能?

我将以下代码放入 BaseCodeCache 中:

public List<BaseCode> getList() {
   return new ArrayList<BaseCode>(idMap.values());
}

但是上面的代码返回了List<BaseCode>。当我这样调用它时:
List<Location> allLocations = LocationCache.getInstance().getList();

那么Java将无法编译并显示以下错误消息:

类型不匹配:无法从List<BaseCode>转换为List<Location>

我可以通过循环获取List<BaseCode>,然后将其转换为List<Location>来解决问题,但这似乎不太对。

这可行吗?

1个回答

4

使用泛型实现如下:

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> {}

这将使您能够在没有任何编译错误的情况下完成以下操作:
LocationCache locationCache = new LocationCache();
locationCache.add(new Location());

List<Location> locations = locationCache.getList();

更好的是,如果您尝试添加或检索错误类型的对象,您将收到编译错误:

locationCache.add(new Department()); // won't compile
List<Department> departments = locationCache.getList(); // won't compile

谢谢,这太棒了。有一个问题。你正在使用的泛型类型有名称吗?如果有,请提一下。TIA - srh
不知道你所说的“泛型类型”是什么意思。上面的例子只是泛型的基础,就像教程中的第一个例子一样。 - Robby Cornelissen
谢谢。我发现你正在使用一个有界类型参数T。 - srh
我们只能掌握裸露的名字,昔日的玫瑰已不再以同样的名字存在。 - Robby Cornelissen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接