Javaレガシーコードをジェネリックに変換 - オブジェクトをタイプに置き換える方法は?
-
03-10-2019 - |
質問
// レガシーコード
void setCacheValue(String name, Object value){
getServletContext().setAttribute(name, value);
}
Object getCacheValue(String name){
return getServletContext().getAttribute(name);
}
//だから私は「タイプ安全」にジェネリックを使用したい
// first, set method seems working perfectly
<T> void setCacheObject(String name, T value){
getServletContext().setAttribute(name, value);
}
//次に、ここにトラブルが発生します
<T> T getCacheValue(String name){
// of course, I cannot change servlet class - it returns Object type
Object value = getServletContext().getAttribute(name);
// would this work:
return (T) value;
// this cast is meaningless... but how should I do it?
}
//これは私が私の中で何を達成するかです 綺麗 呼び出しコード:
{
double x = 1.2;
setCacheValue("x", x);
//...
// later
Double value = getCacheValue("x");
// too bad cannot use primitive type - it cannot handle null
}
それで、これを行う正しい方法は何ですか?
解決
それは確かに不可能です。 「コンクリート」に合格する必要があります T
どういうわけかメソッド引数として、実際のタイプが実行時にわかっているように。一般的に使用されるアプローチは、それを渡すことです Class<T>
, 、あなたが利用できるように Class#cast()
:
<T> T getCacheValue(String name, Class<T> type) {
return type.cast(getServletContext().getAttribute(name));
}
次のように使用できます。
Double value = getCacheValue("x", Double.class);
他のヒント
マップジェネリックは、マップのすべての値のタイプをサポートしますが、特定の値の異なるタイプではありません。あなたはそれを偽造する方法を見ることができます ここ. 。基本的に、アイデアは、キーにタイプの安全性を持たなければならないということです。キーには、単に価値に関連するために存在する一般的なタイプがあります。
一日の終わりには、安全でないキャストなしではそれを行うことはできませんが、キャストに問題がある可能性が非常に低い方法で、それを行うことができます。クラスのユーザー。
実際にそれもコンパイルします:
public class Test
{
<T> T getCacheValue(String name){
// of course, I cannot change servlet class - it returns Object type
Object value = getServletContext().getAttribute(name);
// would this work:
return (T) value;
// this cast is meaningless... but how should I do it?
}
public static void main(String... args)
{
Test t = new Test();
Double double = t.<Double>getCacheValue("Double");
}
}
それはちょっと無意味です(TypeCheckを追加する場合)が、私はそれが興味深いと感じました。
所属していません StackOverflow