1

戻り値がテンプレートに設定されている場合、テンプレート変数のデータ型は何だろうと思っていました。これはどこかのコードで見たことがありますが、セッションから取得した値をどこにキャストするのかわかりません。

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

この外側のコードは次のとおりです。

MyClassType type = request.getFromSessionMap("abc");

オブジェクトにキャストするときに、この行で ClassCastException が発生します。しかし、session.getAttribute("abc") を監視するように追加すると、タイプが MyClassType であることが示されます。どんな助けでも大歓迎です。

どうやら、テンプレートを使用するためのこの特別なコードにより、 getFromSessionMap の戻り値が変数型になるため、キャストは必要ありません。これはすべてのケースで機能しますが、コードの一部で突然失敗しました。

4

4 に答える 4

6

どうやら、テンプレートを使用するためのこの特別なコードにより、 getFromSessionMap の戻り値が変数型になるため、キャストは必要ありません。

基本的に、の結果の取得と への代入の間のどこかに型キャストが必要です。Java 言語 (および JVM)では、インスタンス (またはそのサブタイプ)ではないオブジェクトを変数に割り当てることはできません。session.getAttribute(sessionKey)MyClassTypeMyClassTypeMyClassType

コードをどのように記述しても、型キャストが発生する必要があります。そして、属性は(明らかに)MyClassType(またはサブタイプ)ではないため、ClassCastException.

本当の問題は、なぜコンパイル エラーが発生しないのかということです。そして答えは@SuppressWarnings("unchecked")!この警告を削除すると、次の行で「安全でない型変換」というエラー メッセージが表示されます。

return (T) session.getAttribute(sessionKey);

実際、Java は (実際の) 型をジェネリック型にキャストすることはできません。そして、それが警告/エラーメッセージが指摘するものです。実際、コードがコンパイルされると、このコードは

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

実際には、これと意味に違いはありません:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

技術的に言えば、これは「型消去」と呼ばれます。

では、型チェック/型キャストは実際にどこで行われているのでしょうか? 答えは次の行にあります。

MyClassType type = request.getFromSessionMap("abc");

ここでは型キャストを記述していませんが、Java コンパイラによって生成されたコードは、値を に代入する前に型キャストを実行しますtype。それはしなければなりません。知る限り、割り当てているインスタンスは任意のオブジェクト型である可能性があるためです。

他の投稿者は、 Class 引数を に追加することを提案していますgetFromSessionMap。それ自体では、これはまったく何もしません。メソッドの本体も次のように置き換える場合:

return clazz.cast(session.getAttribute(sessionKey));

メソッドが実際に実際の型チェックを行うようにします。しかし、これClassCastExceptionは別の場所に投げられるだけです。そして、割り当てステートメントはまだ隠し型キャストを行います!!

于 2009-11-12T10:23:41.300 に答える
0

質問の例では、戻り値の型はT. 消去さObjectれた型は、暗黙的にT extends Object. 実際のキャストは、呼び出し元のメソッドのバイトコードで実行されます (これを確認するために使用できますjavap -c)。

一般に、セッション内の「最上位」オブジェクトの数はできるだけ少なくする必要があります。これを行う利点の 1 つは、このようなハッキーなメソッドが不要になることです。

于 2009-11-12T09:58:33.430 に答える
0

私のコードで ClassCastException が発生したため、何か助けていただければ幸いです。

を取得している場合ClassCastExceptionは、次のコードのように、何かをそうでないものにキャストしようとしていることを意味します。

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

ClassCastException「java.lang.String は java.util.Date にキャストできません」のようなわかりやすい詳細メッセージが必要です。

于 2009-11-12T10:03:22.067 に答える
0

メソッド本体内で型キャストを使用します ( '(T)session.getAttribute(sessionKey)' )。

つまり、コンパイラに「オブジェクトが IS-A T を返し、そうでない場合はエラーを処理する準備ができていることを絶対に確信しています」と明示的に言うことを意味します。

ここで、属性タイプに関する仮定が正しくなく、エラーが発生しました。したがって、すべてが正しく、実行時はすでにIS-A MyClassTypeではない実際の属性オブジェクト タイプを提供しています。

于 2009-11-12T10:21:55.463 に答える