2017-02-23 96 views
2

我有以下方法:LAMBDA泛型類型界限

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

我想通過getObjectFromMessage作爲一個參數必須清楚交代提供給我一個拉姆達。然後,lambda可以提供它期望在消息中找到的對象的類,並獲取它的一個實例。有沒有辦法做到這一點,而不會丟失類型信息?

我可以強制它與鑄造和一些對象邊界一起工作,但我真的很想讓消費者知道,如果它通過了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

這方面的一些想法...這是否調用另一個函數添加任何東西的功能?

例如:

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

有至少3個實體正在此間管理泛型類型:

  1. 包含消息字符串的類。
  2. 將消息字符串反序列化爲對象的函數。
  3. 調用解串器函數的函數。

我期待的問題是,持有消息字符串的對象也負責反序列化?如果是這樣,你可以考慮在那裏聲明通用類型。這將防止需要傳遞類型到解串器的功能,例如這可以進一步簡化:

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

我已經聲明ReadType爲:

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

還實現了一個簡單的測試,以檢查輸出和想象這會如何使用:

@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

其他代碼中存在很多隱藏的複雜性,這會使擁有消息的類非常醜陋,從而增加泛型類型參數。你在這裏的實現,擁有類擁有泛型類型,是我正在遷移 - 因爲在這種情況下,我需要改變類型,但保持向前兼容與以前的類型,直到我所有的舊服務器都不在的服務。但這是共享代碼,因此添加第二種可能的輸入類型的另一種類型參數會將下游的醜陋推向所有派生類。 –