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

}

您的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 涵盖了这些示例。泛型方法。

public <T> T get(String key)
{
    return (T)storage.get(key);
}

具有此类签名的方法将根据调用代码推断T,并且T将被允许为任何内容。

此代码将对象从storage中获取,并将其强制转换为调用方请求的任何类型。 这应该会给你一个编译警告,告诉你强制转换是不安全的,并且该警告是正确的,因为你发现的原因。 Java将此作为警告,而不是编译错误,因为在某些极少数情况下可能是必要的,并且可以小心安全地完成。

最新更新