Javaレガシーコードをジェネリックに変換 - オブジェクトをタイプに置き換える方法は?

StackOverflow https://stackoverflow.com/questions/2783613

質問

// レガシーコード

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を追加する場合)が、私はそれが興味深いと感じました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top