Java - 隐式泛型类型推理规则

时间:2015-01-26 19:16:38

标签: java

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?它如何推断类型 - 可能来自运营商(ifassignment等)?

编辑

另外,为什么第二个例子会产生编译错误?!

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();
        }
    }


}

2 个答案:

答案 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涵盖了这些代码。

相关问题