19

さまざまな Java 型 (文字列、ブール値など) の値を一緒に保持するコンテナー オブジェクトが正しく作成されていません。

public class BadlyCreatedClass {
    public Object get(String property) {
        ...;
    }
};

そして、この方法で値を抽出します

String myStr = (String) badlyCreatedObj.get("abc");
Date myDate = (Date) badlyCreatedObj.get("def");

このオブジェクトを使用して新しいコードを作成する必要があり、これを行うためのクリーンな方法があるかどうかを確認しようとしています。より具体的には、以下のどの方法が好ましいですか?

明示的なキャスト

String myStr = (String) badlyCreatedObj.get("abc")
Date myDate = (Date) badlyCreatedObj.get("def");

ジェネリックキャストの使用

public <X> X genericGet(String property) {

}

public String getString(String property) { 
return genericGet(property); 
}

public Date getDate(String property) { 
return genericGet(property); 
}

Class.cast の使用

<T> T get(String property, Class<T> cls) {
    ;
}

私はSO Javaジェネリック関数に関するいくつかの関連する質問を経験しました:ジェネリック型を返す方法Javaジェネリック戻り型はすべて、そのような型キャストは危険であると言っているようですが、どのメソッドがあなたが好きですか?

ありがとう

4

6 に答える 6

3

ジェネリック キャスト アプローチにより、コンパイラはチェックされていない警告を発行します。unchecked 警告は、キャストが実行時に (完全に) チェックされていないことを示します。つまり、値が適切な型でなくても成功する可能性があります。これにより、宣言された型と互換性のない値が変数に保持される可能性があります。これは、Java 言語仕様でヒープ汚染と呼ばれる状況です。

次のプログラムはこれを示しています。

class Holder {
    Object value;

    Holder(Object value) {
        this.value = value;
    }

    <T> T get() {
        return (T) value;
    }
}

class C<T> {
    T value;

    C(Holder h) {
        value = h.get();
    }
}

public class Test {
    public static void main(String [] args) throws IOException {
        Holder holder = new Holder("Hello");
        C<Integer> c = new C<Integer>(holder);
        System.out.println("I just put a String into a variable of type Integer");

        // much later, possibly in a different part of your program
        c.value.longValue(); // throws ClassCastException
    }
}

したがって、チェック キャストを使用することを強くお勧めします。通常のキャスト (最初のアプローチ) と反射キャスト (3 番目のアプローチ) の両方がチェックされます。ただし、リフレクティブ キャストはパラメーター化された型でList<String>.classは機能しません (コンパイルされません ...)。

したがって、最も単純で柔軟な安全なソリューションは、通常のキャストです。

于 2013-04-20T11:16:40.997 に答える