【发布时间】:2013-04-28 22:41:23
【问题描述】:
我以前从来没有机会玩过泛型(比如编写泛型类),但现在需要,我遇到了一些困惑。
有这个接口,它是 something 的包装器。实现不是集合,因此,每个实例只能访问一个 something。
public interface Resource<T> {
// Expected operations:
void write(ResourceState state);
ResourceState read();
}
作为实现,我希望有一个ExclusiveResource<T> 和一个ShareableResource<T>,它们主要/仅在使用的锁定方案(分别为常规锁和读写锁)上有所不同。
至于read和write是如何执行的,我打算使用Strategy模式。
例如,我可能有
// This would implement a Strategy<File>.
FileStrategy fs = new FileStrategy();
Resource<File> r = new ExclusiveResource<File>(fs);
现在,我还获得了这些资源的某种集合,例如资源池。
我想将一个键映射到资源池中的每个资源,并且我想添加、检索和删除资源,但我不确定如何声明映射和方法。我尝试了以下方法:
public class ResourcePool {
// instance variables
private final Map<String, Resource<?>> map;
/** Empty constructor of objects of class ResourcePool. */
public ResourcePool() {
map = new HashMap<String, Resource<?>>();
}
/** */
public Resource<?> get(String s) {
return map.get(s);
}
/** */
public void add(String s, Resource<?> r) {
map.put(s, r);
}
// ...
}
这似乎不是最合适的方法,引用 Josh Bloch 的话,Effective Java Reloaded:
用户无需考虑通配符即可使用您的 API。
我用以下方法测试了这段代码:
public static void test() {
ResourcePool rp = new ResourcePool();
Resource<String> r1 = new ShareableResource<>("test");
Resource<Integer> r2 = new ShareableResource<>(1);
Resource<List<String>> r3 = new ShareableResource<>(
Arrays.asList(new String[]{"1", "2"})
);
// These are all ok.
rp.add("1", r1);
rp.add("2", r2);
rp.add("3", r3);
// This results in a compiler error (incompatible types).
Resource<String> g1 = rp.get("1");
// This results in a compiler warning (unsafe operation).
Resource<String> g2 = (Resource<String>) rp.get("1");
}
我不喜欢这样,当代码编译时出现警告。让我感到内疚,并且似乎暗示了糟糕的编码。
所以,我的问题是我应该如何处理这种情况。
这是做我想做的事情的正确方法吗?
这样做可以做到没有不安全的操作吗?
【问题讨论】:
-
我认为有必要查看 Resource 的实现来解决这个问题。我认为你最好的选择是从资源中删除泛型类型,只使用普通接口。
-
@KevinBowersox 我没有提供有关资源的更多详细信息,因为担心问题可能会太长,但我会用我打算如何处理资源以及什么来更新它预计会实施。
-
我不确定有什么方法可以避免不安全的演员表。想想你熟悉的泛型类型,例如
List<E>。现在想象一下有一个List<List<?>>,你怎么能以一种类型安全的方式使用这个参数化类型呢?我不确定你能不能。除非您非常了解列表中每个项目所包含的内容,否则您永远不会知道列表返回的类型
标签: java generics collections wildcard