119

C++ 時代に C スタイルのキャスト演算子の弊害について教わった私は、最初は Java 5 でメソッドが追加されたことを知ってうれしく思いましjava.lang.Classcast

最終的に、キャストをオブジェクト指向の方法で処理できるようになったと思いました。

結局のところ、C++Class.castと同じではありません。static_castそれはもっと似ていreinterpret_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++ と同様の言語構造としてキャスト演算子を提供する必要がありますか?
4

8 に答える 8

129

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)) 使用すると最適化される可能性がありますが、それを使用している人を見たことがありません。このため、この最適化をコンパイラに組み込む努力はいくらか価値がありません。

于 2009-10-12T15:58:49.793 に答える
3

C++ と Java は異なる言語です。

Java C スタイルのキャスト演算子は、C/C++ バージョンよりもはるかに制限されています。事実上、Java キャストは C++ の dynamic_cast に似ており、オブジェクトを新しいクラスにキャストできない場合、実行時 (またはコンパイル時にコードに十分な情報がある場合) 例外が発生します。したがって、C 型キャストを使用しないという C++ の考え方は、Java ではお勧めできません。

于 2009-10-12T15:57:38.813 に答える