2017-02-23 18 views
2

私は次の方法があります。ラムダジェネリック型境界

public <T> T getObjectFromMessage(Class<T> clazz) { 
     return gson.fromJson(compressor.decompress(message.getJsonInputs(s3)), clazz); 
    } 

を私が私に与えていますラムダへのパラメータとしてgetObjectFromMessage渡したいです。ラムダは、メッセージ内で見つかると予想されるオブジェクトのクラスを提供し、そのインスタンスを戻すことができます。タイプ情報を失うことなくこれを行う方法はありますか?

キャストといくつかのオブジェクト境界で動作するように強制することができますが、Class<T>を渡すと、一般的な境界を持つメソッドと同じようにTが返されることを消費者に伝えたいと思います。かかるラムダで

は、私は現在のように宣言体操を行うことを余儀なくしています:

public void consume(Function<Class<Object>, Object> getInputs){ 
    MyType type = (MyType)getInputs.apply(MyType.class); 
} 

が、私は入力を解析してみたい場合がある、と私は失敗した場合、別のクラスを試してみてください。ジェネリックは実際にはメソッドごとに呼び出される必要があります。

+0

を唯一 'Object.class'は'クラスを入力しているので、私は、 '>、それは'機能だろうと思ったでしょう?'。 –

+0

'getObjectFromMessage'の呼び出しのコンテキストを表示できますか? –

+0

オブジェクトを型バインドとして使用することはバインドされていないようです – efekctive

答えて

7

あなたは、一般的な方法でカスタム関数インタフェースを定義することができます別の関数を呼び出す関数は何も追加しない...この上

interface TypeFunction { 
    <T> T apply(Class<T> clazz); 
} 

public void consume(TypeFunction getInputs) { 
    MyType type = getInputs.apply(MyType.class); 
} 
+1

これはシンプルですが鮮やかですが、ありがとうございます。 –

+0

なぜインタフェースの代わりにメソッドを汎用化するのですか? –

+1

@LewBlochインターフェースを生成すると、 'getInputs'が特定の型にロックされます。 OPは 'Class 'に対して 'T'を返すことを望んでいます。 – shmosel

1

いくつかの考えを?例えば

  1. メッセージ文字列を含むクラス:

    <T> T consume(ReadType<T> typeFunction) { 
        T type = typeFunction.read(); 
        return type; 
    } 
    

    ここで、少なくとも3つのエンティティで管理されている一般的な種類があります。

  2. メッセージ文字列をオブジェクトに逆シリアル化する関数。
  3. デシリアライザ機能を呼び出す関数。

メッセージ文字列を保持するオブジェクトもデシリアライズの原因であると思いますが、もしそうならジェネリック型を宣言することを検討することができます。これは、デシリアライザの機能にタイプを渡す必要性を妨げる、例えばこれをさらに簡素化することができます。

interface ReadType<T> { 
    T read(); 
} 

もチェックする簡単なテストを実施し:

<T> ReadType<T> readObjectFromMessage(Class<T> clazz) { 
    return() -> readValue(clazz); 
} 

私はReadTypeを宣言しました出力と、これは使用されるかもしれない方法を可視化する:

@Test 
public void consumeTypeTest() throws Exception { 
    String message = "{\"foo\":\"hello\",\"bar\":\"world\"}"; 
    GenericFunctions genericFunctions = new GenericFunctions(message); 

    ReadType<MyType> myTypeFromMessage = genericFunctions.readObjectFromMessage(MyType.class); 
    MyType myType = genericFunctions.consume(myTypeFromMessage); 

    Assert.assertThat(myType, equalTo(new MyType().setFoo("hello").setBar("world"))); 
} 
+0

コードの残りの部分には、ジェネリック型のparamをメッセージをかなり醜いクラスに追加する隠された複雑さがたくさんあります。ここでは、所有するクラスがジェネリック型を保持している実装があります。この場合、タイプを変更する必要がありますが、以前のすべての古いサーバーがなくなるまで以前のタイプとの下位互換性を維持する必要があるからですサービスのしかし、これは共有されたコードなので、 2番目に可能な入力タイプの別のタイプのパラメータは、醜いダウンストリームをすべての派生クラスにプッシュします。 –