奇怪的泛型行为.被早期擦除?

joe*_*l_s 10 java generics javac type-erasure

我今天遇到了一些奇怪的Java泛型行为.以下代码编译正常并按预期工作:

import java.util.*;

public class TestGeneric
{
    public static void main(String[] args)
    {
        GenericClass<Integer> generic = new GenericClass<Integer>(7);
        String stringFromList = generic.getStringList().get(0);
    }

    static class GenericClass<A>
    {
        private A objA;
        private List<String> stringList;

        GenericClass(A objA)
        {
            this.objA = objA;
            stringList = new ArrayList<String>();
            stringList.add("A string");
            stringList.add("Another string");
        }

        A getObjA()
        {
            return objA;
        }

        List<String> getStringList()
        {
            return stringList;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是如果你将变量泛型的类型更改为GenericClass(注意没有类型参数),则编译失败并显示消息"不兼容的类型:java.lang.Object无法转换为java.lang.String".

任何包含具有具体类型参数的泛型对象的泛型类似乎都会发生此问题.一些谷歌搜索没有发现任何东西,JLS没有提到这种情况?我做错了什么或者这是javac中的错误?

Rad*_*def 4

原始类型GenericClass被视为已删除,包括类未声明的泛型类型。因此getStringList返回原始值List而不是参数化值List<String>

我发现很难在 Java 规范中找到一件事来指出这一点,但这是正常行为。

这是另一个例子。

public class Test {
    public static void main(String[] args) {
        String s;

        // this compiles
        s = new Generic<Object>().get();
        // so does this
        s = new Generic<Object>().<String>get();

        // this doesn't compile
        s = new Generic().get();
        // neither does this
        s = new Generic().<String>get();
    }
}

class Generic<A> {
    <B> B get() { return null; }
}
Run Code Online (Sandbox Code Playgroud)

和 都AB擦除,但B由方法声明。这很好奇。

这种令人惊讶的细微差别就是为什么必须警告不要使用原始类型。