java - 使用括号的通用转换

标签 java generics

我试图理解接下来的事情。接下来将打印此 block 代码

example.TestGenerics$One@49c2faae
example.TestGenerics$Two@20ad9418

所以我认为转换已成功完成,但我希望列表中的第二个对象出现 ClassCastException。

public class TestGenerics
{
    public static void main(String[] args)
    {
        Generic<One> integerGeneric = new Generic<One>(new Container(Lists.<Object>newArrayList(new One(), new Two())));
        integerGeneric.checkContainer();
    }

    static class Generic<T>
    {
        private Container container;

        public Generic(Container container)
        {
            this.container = container;
        }

        public void checkContainer()
        {
            for (Object key : container.getObjects())
            {
                final T genericKey = (T)key;
                System.out.println(genericKey);
            }
        }
    }

    static class Container
    {
        Iterable<Object> objects;

        public Container(Iterable<Object> objects)
        {
            this.objects = objects;
        }

        public Iterable<Object> getObjects()
        {
            return objects;
        }
    }

    static class One
    {

    }

    static class Two
    {

    }
}

附言 我还遇到了泛型类型转换(使用 (T)object)返回 null 而不是抛出异常 ClassCastException 的问题,但我无法重现它。如果有人知道这件事,请在这里发表评论

最佳答案

I have learned that JVM see generic like Object type in runtime (or nearest type, if it has "exists")

不一定Object .无限泛型就是这种情况,就像在您的代码中一样。如果它有界限,比如 <T extends ParentClass> ,则运行时类型将为 ParentClass .由于您的代码没有限制,它将是 Object这不会在 Actor 阵容中造成任何问题。

现在,为了改进类型检查并获得正确的编译器错误,您需要将通用类型添加到 Container :

static class Container<T> {
    Iterable<T> objects;

    public Container(Iterable<T> objects) {
        this.objects = objects;
    }

    public Iterable<T> getObjects() {
        return objects;
    }
}

并更新Generic避免使用原始 Container类:

static class Generic<T> {
    private Container<T> container;

    public Generic(Container<T> container) {
        this.container = container;
    }

    public void checkContainer() {
        for (T key : container.getObjects()) {
            final T genericKey = key;
            System.out.println(genericKey);
        }
    }
}

现在添加一个diamond operator在你的主要方法中:

Generic<One> integerGeneric = new Generic<One>(new Container(Lists.<Object>newArrayList(new One(), new Two())));

然后您将拥有:

Generic<One> integerGeneric = new Generic<>(new Container<>(Lists.newArrayList(new One(), new Two())));

编译器错误表明Lists.newArrayList(new One(), new Two())如果所需类型为 One,则不允许.


顺便说一句:您仍然可以通过使用原始类型或 Object 来绕过此编译器检查。作为通用类型,这仍然不会导致运行时异常,因为 ContainerGeneric类没有界限。

关于java - 使用括号的通用转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36498368/

相关文章:

java - 将多个用户输入存储在数组中

java - 在我不知道类型的对象上调用方法

具有多个子类型的 Scala 泛型(元组)类型

java - 需要帮助将特定字符与 Java 正则表达式匹配

java - Java 中的 PHP base_convert

java - 在 SocketChannel 上通过 TCP 读取未定义字节数的流

java - 使用 simpledateformat 进行日期解析

java - 我可以为泛型函数提供正确的类型信息吗?

java - 保留通用参数的关联类

kotlin - 如何使用函数中的泛型来避免重复代码?