import java.util.HashMap;
class Holder
{
HashMap<String, Object> storage;
public Holder()
{
storage = new HashMap<String, Object>();
}
public <T> T get(String key)
{
return (T)storage.get(key);
}
public void add(String key, Object value)
{
storage.put(key, value);
}
}
public class Test022 {
public static void main(String[] args) throws Exception {
Holder h = new Holder();
h.add("1", false);
h.add("2", new String[]{"3", "4", "5", null, null});
Holder h2 = h.get("2"); // compiles OK ?! fails at runtime with ClassCastException?!
if (h.get("2")) // compiles OK ?! fails at runtime with ClassCastException?!
{
System.out.println();
}
}
}
请参阅标有// compiles OK ?! fails at runtime with ClassCastException?!
的2行。我想知道为什么这些编译好吗?有谁引用JLS?它如何推断类型 - 可能来自运营商(if
,assignment
等)?
编辑
另外,为什么第二个例子会产生编译错误?!
import java.util.HashMap;
class Holder
{
HashMap<String, Object> storage;
public Holder()
{
storage = new HashMap<String, Object>();
}
public <T> T get(String key)
{
return (T)storage.get(key);
}
public void add(String key, Object value)
{
storage.put(key, value);
}
}
public class Test022 {
public static boolean test(String[] s){
return false;
}
public static void main(String[] args) throws Exception {
Holder h = new Holder();
h.add("1", false);
h.add("2", new String[]{"3", "4", "5", null, null});
if (test(h.get("2"))) // This doesn't compile ?!
{
System.out.println();
}
}
}
答案 0 :(得分:3)
public <T> T get(String key)
{
return (T)storage.get(key);
}
具有类似签名的方法将根据调用代码推断T
,并且T
将被允许为任何内容。
此代码从storage
中获取对象,并将其转换为调用者请求的任何类型。这个应该给你一个编译警告,它会告诉你演员表是不安全的,并且这个警告对于你发现的原因是正确的。 Java使这成为一个警告,而不是编译错误,因为在某些极少数情况下它可能是必要的,并且可以安心地完成 。
答案 1 :(得分:3)
您的Holder
并未定义为通用,而是您已将这些方法设为通用方式。我想你想要
class Holder<T> {
HashMap<String, T> storage;
public Holder() {
storage = new HashMap<String, T>();
}
public T get(String key) {
return storage.get(key);
}
public void add(String key, T value) {
storage.put(key, value);
}
}
然后,因为Holder
现在是通用的 - 您在创建时指定了类型
Holder<String[]> h = new Holder<>();
// h.add("1", false); // <-- Pick a type...
h.add("2", new String[]{"3", "4", "5", null, null});
您发布的代码是通用方法的示例,JLS-8.4.4. Generic Methods涵盖了这些代码。