テンプレートの種類のテンプレートは、戻り値(Java)のであれば
-
19-09-2019 - |
質問
私はリターンがテンプレートに設定されている場合、テンプレート変数のデータ型が何であるか疑問に思いました。私はどこかのコードでこれを見てきましたが、それはセッションから取得した値をキャストしないところ私は知りません。
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の戻り値変数の型とキャストが不要になります。これは、すべての場合に動作しますが、突然、それは、コードの一部に失敗します。
解決
使用するためのどうやら、この特別なコード テンプレートはのリターンを作ります getFromSessionMap変数の型と したがって、キャストは必要ありません。
基本的には、がどこかsession.getAttribute(sessionKey)
とMyClassType
への割り当ての結果を得ることとの間に型キャストをなければなりません。 Java言語(およびJVM)の MyClassType
インスタンス(またはそのサブタイプ)ではありませんのいくつかのオブジェクトはMyClassType
変数に割り当てることができません。
どんなにあなたがコードを書くか、を型キャストは、を発生することがありません。そして、(明らかに)属性以来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
する値を割り当てる前に型キャストを行います。それはする必要があります。限り、それは知っているとして、それが代入されるインスタンスは可能性があるため、のいずれかののオブジェクト型ます。
他のポスターはgetFromSessionMap
に、クラスの引数を追加することを示唆しています。それ自体で、これがないの絶対に何もないの。あなたも持つメソッドの本体を交換する場合:
return clazz.cast(session.getAttribute(sessionKey));
あなたは、実際に本物の型チェックを行うためのメソッドが発生します。しかし、これだけで原因ClassCastException
は別の場所でスローされます。そして、代入文は、の、まだ隠された型キャストを行います!! の
他のヒント
質問の例では、戻り値の型はT
です。消去タイプは暗黙のうちに、Object
、としてT extends Object
されます。実際のキャストが(あなたがそれを見てjavap -c
を使用することができます)、呼び出し元のメソッドのバイトコードで実行されます。
一般的に、あなたは可能な限り小さくセッションで「トップレベル」のオブジェクトの数を維持する必要があります。それを行うの利点の一つは、これらのようなハック方法の必要性がもはや存在しません。
私のコードは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にキャストすることはできません」のような、啓発された詳細メッセージを持つ必要があります。
あなたは、メソッド本体内にキャストタイプ(の '(T)session.getAttribute(SESSIONKEY)' の)を使用します。
それはあなたが明示的にの<全角>「そうでない場合、私は返されるオブジェクトはTおよびエラーを処理する準備ができて、されていることを絶対的に確信している」コンパイラに言うことを意味します。
ここでは、属性タイプについてのあなたの仮定が間違っていたとエラーが発生しました。だから、すべてが正しく、ランタイムがまだない本物の属性オブジェクトの種類を提供します。<全角> IS-A のMyClassTypeます。