20

私は最近、次のようなコードに出くわしました。

Object o = .. ;
Foo foo = Foo.class.cast(o);

実際には、java.lang.Class にキャスト メソッドがあることさえ知らなかったので、ドキュメントを調べたところ、収集した内容から、これは単純に Class オブジェクトが表すクラスへのキャストを実行します。したがって、上記のコードはほぼ同等です

Object o = ..;
Foo foo = (Foo)o;

それで、単に「古い方法」でキャストするのではなく、キャストメソッドを使用したいのはなぜだろうと思いました。キャストメソッドの使用が単純なキャストを行うよりも有益である良い例はありますか?

4

8 に答える 8

8

あなたが示したように正確に使用されることはあまりないと思います。私が見た最も一般的な使用法は、ジェネリックを使用している人々がこれと同等のことをしようとしている場合です:

public static <T extends Number> T castToNumber(Object o) {
    return (T)o;
}

型消去のために、これは実際には何も役に立ちません。

これは機能し、タイプセーフです(モジュロClassCastExceptions):

public static <T extends Number> T castToNumber(Object o, Class<T> clazz) {
    return clazz.cast(o);
}

編集: Google グアバからの使用例のカップル:

于 2011-10-26T08:47:45.930 に答える
4

Java では、猫の皮を剥ぐ方法が複数あることがよくあります。このような機能は、フレームワーク コードがある場合に役立ちます。Class オブジェクト インスタンスと Object インスタンスを受け取り、Object ケースをクラスとして返すメソッドを想像してください。

public static void doSomething(Class<? extends SomeBaseClass> whatToCastAs,Object o)
    {
        SomeBaseClass castObj =  whatToCastAs.cast(o);
        castObj.doSomething();
    }

一般に、十分でない場合を除き、より単純なキャストを使用します。

于 2011-10-26T08:44:42.867 に答える
2

場合によっては、実行時にオブジェクトをキャストする型しかわからないことがあります。そのような場合は、キャスト メソッドを使用する必要があります。

于 2011-10-26T08:45:43.580 に答える
2

Foo.class.cast(o)と書く理由はまったくありません(Foo)o

一般に、 が具体化可能な型 である場合X thenClass<X> clazzclazz.cast(o)と同じ(X)oです。

したがって、すべての型が具体化可能である場合、メソッドClass.cast()は冗長で役に立ちません。

残念ながら、現在のバージョンの Java では消去が行われるため、すべての型が再定義できるわけではありません。たとえば、型変数は具体化できません。

Tが型変数の場合、キャストは(T)oチェックされません。これは、実行時に の正確な型がTJVM に認識されないためです。JVM は、oが本当に typeかどうかをテストできませんT。キャストが誤って許可される可能性があり、後で問題が発生する可能性があります。

これは大きな問題ではありません。通常、プログラマーが(T)o. キャストはアプリ ロジックによってチェックされます。

キャストの時点でa が利用可能であると仮定すると、実行時にClass<T> clazz何があるかがわかります。Tランタイム チェックを追加してo、実際にT.

check clazz.isInstance(o);
(T)o;

そして、これは本質的に何をするかClass.cast()です。

どのような場合でもキャストが失敗することは想定していません。したがって、正しく実装されたアプリでは、チェックclazz.isInstance(o)は常に成功する必要があります。したがって、コードが正しいという前提の下で -clazz.cast(o)と同等です。(T)o

コードが正しく、キャストが安全であることを証明できる場合は、パフォーマンス上の理由(T)oから好む可能性があります。clazz.cast(o)別の回答で発生した例ではMutableClassToInstanceMap、キャストが安全であることは明らかであるため、シンプル(T)oで十分でした。

于 2011-10-26T11:36:57.503 に答える
1

class.cast はジェネリック型用に設計されています。

ジェネリック パラメーター T を使用してクラスを構築する場合、クラスを渡すことができます。その後、静的チェックと動的チェックの両方でキャストを実行できますが、(T) では提供されません。また、(その時点で) チェックされているため、チェックされていない警告も生成されません。

于 2011-10-26T08:45:36.887 に答える
1

その一般的な例は、クラス オブジェクトといくつかの条件で参照されるエンティティのコレクションを永続レイヤーから取得する場合です。返されたコレクションにはチェックされていないオブジェクトが含まれている可能性があるため、それを指定された G_H としてキャストすると、値がアクセスされたときではなく、この時点でキャスト例外がスローされます。

この 1 つの例は、チェックされていないコレクションを返す DAO からコレクションを取得し、サービスでそれを反復処理する場合です。この状況は、ClassCastException につながる可能性があります。

それを解決する1つの方法は、必要なクラスとチェックされていないコレクションがあるため、それを反復処理し、DAO内にキャストしてコレクションをチェックされたコレクションに変換し、その後それを返すことです。

于 2011-10-26T09:04:53.843 に答える
0

Javaの「キャスト」、たとえば(Number)var、括弧内のものが参照型である場合、実際には2つの部分で構成されます。

  • コンパイル時:キャスト式の結果には、キャスト先のタイプのタイプが含まれます
  • 実行時:チェック操作を挿入します。これは基本的に、オブジェクトがそのクラスのインスタンスでない場合は、をスローしClassCast Exceptionます(キャスト先が型変数の場合、チェックするクラスは下位になります)型変数の境界)

構文を使用するには、コードを作成するときにクラスを知っている必要があります。コンパイル時に、キャストするクラスがわからないとします。あなたは実行時にそれを知っているだけです。

さて、あなたは尋ねるでしょう、それではキャストのポイントは何ですか?コンパイル時に式を目的の型に変換するためのキャストのポイントではありませんか?したがって、コンパイル時にタイプがわからない場合は、コンパイル時にメリットはありませんよね?本当ですが、それは上記の最初の項目にすぎません。キャストのランタイムコンポーネント(上記の2番目の項目)を忘れています。オブジェクトをクラスと照合します。

したがって、ランタイムキャスト(つまりClass.cast())の目的は、オブジェクトがクラスのインスタンスであることを確認し、そうでない場合は例外をスローすることです。これとほぼ同等ですが、より短いです。

if (!clazz.isInstance(var))
    throw new ClassCastException();

渡されたクラスのtypeパラメーターに基づく優れたreturn型もあると言う人Class.cast()もいますが、それはとにかくコンパイル時のキャストによって提供されるコンパイル時の機能にすぎません。したがって、その目的のためにを使用する意味はありませんClass.cast()

于 2011-10-26T20:32:00.367 に答える
0

あなたはこれを持っているかもしれないので:

Number fooMethod(Class<? extends Number> clazz) {
    return clazz.cast(var);
}
于 2011-10-26T08:44:51.627 に答える