Java Class.cast() vs. cast operator

2022-08-31 09:02:28

在我C++的日子里,我被教导了C型强制转换运算符的邪恶,起初我很高兴地发现Java 5已经获得了一种方法。java.lang.Classcast

我以为我们终于有了处理选角的OO方式。

事实证明,这与C++年不同。它更像是.它不会在预期位置生成编译错误,而是会推迟到运行时。下面是一个简单的测试用例,用于演示不同的行为。Class.caststatic_castreinterpret_cast

package test;

import static org.junit.Assert.assertTrue;

import org.junit.Test;


public class TestCast
{
    static final class Foo
    {
    }

    static class Bar
    {
    }

    static final class BarSubclass
        extends Bar
    {
    }

    @Test
    public void test ( )
    {
        final Foo foo = new Foo( );
        final Bar bar = new Bar( );
        final BarSubclass bar_subclass = new BarSubclass( );

        {
            final Bar bar_ref = bar;
        }

        {
            // Compilation error
            final Bar bar_ref = foo;
        }
        {
            // Compilation error
            final Bar bar_ref = (Bar) foo;
        }

        try
        {
            // !!! Compiles fine, runtime exception
            Bar.class.cast( foo );
        }
        catch ( final ClassCastException ex )
        {
            assertTrue( true );
        }

        {
            final Bar bar_ref = bar_subclass;
        }

        try
        {
            // Compiles fine, runtime exception, equivalent of C++ dynamic_cast
            final BarSubclass bar_subclass_ref = (BarSubclass) bar;
        }
        catch ( final ClassCastException ex )
        {
            assertTrue( true );
        }
    }
}

所以,这些是我的问题。

  1. 应该被放逐到仿制药的土地吗?在那里,它有相当多的合法用途。Class.cast()
  2. 编译器在使用时是否应该生成编译错误,并且在编译时可以确定非法条件?Class.cast()
  3. Java是否应该提供一个强制转换运算符作为类似于C++的语言构造?

答案 1

我只习惯于避免在“通用土地”中发出警告。我经常看到这样的方法:Class.cast(Object)

@SuppressWarnings("unchecked")
<T> T doSomething() {
    Object o;
    // snip
    return (T) o;
}

通常最好将其替换为:

<T> T doSomething(Class<T> cls) {
    Object o;
    // snip
    return cls.cast(o);
}

这是我遇到过的唯一用例。Class.cast(Object)

关于编译器警告:我怀疑这对编译器来说并不特别。当静态使用时,它可以进行优化(即 而不是),但我从未见过有人使用它 - 这使得将这种优化构建到编译器中的努力有些毫无价值。Class.cast(Object)Foo.class.cast(o)cls.cast(o)


答案 2

首先,强烈建议您不要进行任何施法,因此您应该尽可能地限制它!您将失去 Java 的编译时强类型功能的优势。

在任何情况下,都应主要在通过反射检索令牌时使用。写起来更习惯用语Class.cast()Class

MyObject myObject = (MyObject) object

而不是

MyObject myObject = MyObject.class.cast(object)

编辑:编译时的错误

总的来说,Java 只在运行时执行强制转换检查。但是,如果编译器可以证明此类强制转换永远不会成功,则编译器可能会发出错误(例如,将一个类强制转换为另一个不是超类型的类,并将最终类类型强制转换为不在其类型层次结构中的类/接口)。在这里,由于 和 是不在彼此层次结构中的类,因此强制转换永远不会成功。FooBar


推荐