2017-02-23 113 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

其他代码中存在很多隐藏的复杂性,这会使拥有消息的类非常丑陋,从而增加泛型类型参数。你在这里的实现,拥有类拥有泛型类型,是我正在迁移 - 因为在这种情况下,我需要改变类型,但保持向前兼容与以前的类型,直到我所有的旧服务器都不在的服务。但这是共享代码,因此添加第二种可能的输入类型的另一种类型参数会将下游的丑陋推向所有派生类。 –