有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用括号的java泛型转换

我试图理解下一件事。下一步将打印此块代码

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

所以我假设cast已经成功完成,但我希望列表中的第二个对象使用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)对象)返回null而不是抛出异常ClassCastException,但我无法重现它。如果有人知道这一点,请在这里发表评论


共 (1) 个答案

  1. # 1 楼答案

    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,这在强制转换期间不会引起任何问题

    现在,为了改进类型检查并获得正确的编译器错误,需要将泛型类型添加到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())));
    

    以及一个编译器错误,指出如果所需类型为One,则不允许使用Lists.newArrayList(new One(), new Two())


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