Map 的参数化类型键
Parameterized type keys for Map
我正在学习 Java,目前正在阅读 Joshua Bloch 的 Effective Java。
在项目 29 中,他讨论了 Map 的参数化类型键以创建类型安全的异构映射。这是代码:
class Favorites {
private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, instance);
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));
}
}
他接着说
A malicious client could easily corrupt the type safety of a Favorites
instance, simply by using a Class object in its raw form. But the
resulting client code would generate an unchecked warning when it was
compiled.
我知道 Class<T>
会被删除为 Class。但我不确定恶意客户端如何在编译时破坏类型安全。我尝试了各种方法,但如我所料,我总是遇到编译错误。
有人能告诉我 Joshua Bloch 在上面引用的那行中到底是什么意思吗?
原始类型是没有通用信息的类型。以下是如何破坏方法的类型安全性:
Favorites favorites = new Favorites();
favorites.putFavorite((Class)Integer.class, "foo"); // no compile error
而这不会编译:
favorites.putFavorite(Integer.class, "foo"); // compile error
因为参数的类型是 Class
(而不是 Class<T>
),所以无法确定泛型方法参数 T
,并且该调用的类型推断被关闭。就好像进行调用的代码是前泛型,java 向后兼容(通过忽略泛型)。
以下是防止该问题的方法:
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
if (!type.isInstance(instance)) // add check for instance type
throw new IllegalArgumentException("Class/instance mismatch");
favorites.put(type, instance);
}
或更残酷(因为您无法通过错误消息提供信息),只需尝试强制转换:
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, type.cast(instance)); // will throw ClassCastException
}
但这只会在 运行时 当恶意代码试图造成破坏时发现问题,但它仍然比在 使用时发现问题要好 其他客户端尝试使用不可靠实例的时间。
我正在学习 Java,目前正在阅读 Joshua Bloch 的 Effective Java。
在项目 29 中,他讨论了 Map 的参数化类型键以创建类型安全的异构映射。这是代码:
class Favorites {
private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, instance);
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));
}
}
他接着说
A malicious client could easily corrupt the type safety of a Favorites instance, simply by using a Class object in its raw form. But the resulting client code would generate an unchecked warning when it was compiled.
我知道 Class<T>
会被删除为 Class。但我不确定恶意客户端如何在编译时破坏类型安全。我尝试了各种方法,但如我所料,我总是遇到编译错误。
有人能告诉我 Joshua Bloch 在上面引用的那行中到底是什么意思吗?
原始类型是没有通用信息的类型。以下是如何破坏方法的类型安全性:
Favorites favorites = new Favorites();
favorites.putFavorite((Class)Integer.class, "foo"); // no compile error
而这不会编译:
favorites.putFavorite(Integer.class, "foo"); // compile error
因为参数的类型是 Class
(而不是 Class<T>
),所以无法确定泛型方法参数 T
,并且该调用的类型推断被关闭。就好像进行调用的代码是前泛型,java 向后兼容(通过忽略泛型)。
以下是防止该问题的方法:
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
if (!type.isInstance(instance)) // add check for instance type
throw new IllegalArgumentException("Class/instance mismatch");
favorites.put(type, instance);
}
或更残酷(因为您无法通过错误消息提供信息),只需尝试强制转换:
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, type.cast(instance)); // will throw ClassCastException
}
但这只会在 运行时 当恶意代码试图造成破坏时发现问题,但它仍然比在 使用时发现问题要好 其他客户端尝试使用不可靠实例的时间。