ジェネリックにデフォルト値を割り当てる

私はリフレクションによってメソッドを呼び出しています。その戻り値の型は汎用です。戻り値をnullにしたくないので、その場合はその汎用型のデフォルト値を割り当てる必要があります。

つまり、リフレクションでメソッドを呼び出すと した後、次のようなコードを実行します。

T resultNotNull = (T) reflectionMethodThatCanReturnNull.invoke(anObject);
// If it's null, let's assign something assignable.
if (resultNotNull == null) {
    if (resultNotNull.getClass().isAssignableFrom(Long.class)) {
        resultNotNull = (T) Long.valueOf(-1);
    } else if (resultNotNull.getClass().isAssignableFrom(String.class)) {
        resultNotNull = (T) "NOTHING";
    } 
}

もちろん、 'resultNotNull == null'の場合、例外を取得せずに 'resultNotNull.getClass()'を呼び出すことはできません。

ジェネリックタイプに応じてデフォルト値を割り当てる方法に関するアイデアはありますか?

コード全体は次のようなものになります。

public class ReflectionTest {
    public class Class1ok {
        public Long method() { return Long.valueOf(1); }
    }   
    public class Class1null {
        public Long method() { return null; }//It returns null
    }   
    public class Class2ok {
        public String method() { return "SOMETHING"; }
    }

    public static void main(String[] args) {
        ReflectionTest test = new ReflectionTest();

        Long notNullValue1 
            = test.methodReturnNotNull(Class1ok.class);//1
        Long notNullValue2 
            = test.methodReturnNotNull(Class1null.class);//-1, not null
        String notNullValue3 
            = test.methodReturnNotNull(Class2ok.class);//"SOMETHING"
    }

    public  T methodReturnNotNull(Class theClass) {
        T resultNotNull = null;
        try {
            Object theObject = theClass.newInstance();
            Method methodThatCanReturnNull = theClass.getMethod("method");
            resultNotNull = (T) methodThatCanReturnNull.invoke(theObject);
        } catch (Exception e) {
           //Meh.
        }

       //If it's null, assign something assignable.
        if (resultNotNull == null) {
            if (resultNotNull.getClass().isAssignableFrom(Long.class)) {
                resultNotNull = (T) Long.valueOf(-1);
            } else if (resultNotNull.getClass().isAssignableFrom(String.class)) {
                resultNotNull = (T) "NOTHING";
            } 
        }
        return resultNotNull;
    }
}
6

2 答え

getReturnType()を使用できます。

private static final Map replacementForNull = new HashMap<>();
static {
    replacementForNull.put(String.class, "NOTHING");
    replacementForNull.put(Long.class, 1L);
}


Method reflectionMethodThatCanReturnNull = ...
T resultNotNull = (T) reflectionMethodThatCanReturnNull.invoke(anObject);
// If it's null, let's assign something assignable.
if (resultNotNull == null) {
    Class returnType = reflectionMethodThatCanReturnNull.getReturnType();
    resultNotNull = replacementForNull.get(returnType);
}
3
追加された
戻り値の型がObjectまたはObjectを返すGenericの場合、getReturnType()はObjectを返します。上の例では、 Long String
追加された 著者 Peter Lawrey,
マップを使用する方がよりエレガントかもしれません。上記を参照。
追加された 著者 Peter Lawrey,
getReturnType()はオブジェクトを返しませんか? Genericsはコンパイル時に消去されます。
追加された 著者 Pablo,
OK、私は質問を間違えた、私は彼が方法 "メソッド"が一般的であることを意味したと思った。
追加された 著者 Pablo,
それはうまくいった。タクンスピーター
追加された 著者 J.A.I.L.,
答えはPeter Lawreyが指摘したように、 getReturnType()を使用しています:T resultNotNull =(T)reflectionMethodThatCanReturnNull.invoke(anObject);//nullの場合は、割り当て可能なものを割り当てましょう。 if(resultNotNull == null){finalクラス<?> returnType = methodGetFkForIncidentDTO.getReturnType(); if(returnType.isAssignableFrom(Long.class)){resultNotNull =(T)Long.valueOf(-1); } else if(returnType.isAssignableFrom(String.class)){resultNotNull =(T) "いいえ"; }}
追加された 著者 J.A.I.L.,

T がインタフェースを実装できないか、基本クラスを拡張できないのはなぜですか?次に、与えられたクラス T のデフォルト値を返す T から静的デフォルトメソッドを呼び出すことができます。長所? switch コードを適切なクラスにカプセル化します。

もちろん、インターフェースがなくても、すべての可能な T クラスは getDefaultValue()のようなメソッドを持つことができます。

0
追加された
いいえ、私は getDefaultValue()メソッドを追加するためにTクラスを変更することも、返されるものを変更することもできません。
追加された 著者 J.A.I.L.,