声明function.Consumer <t>可以消耗一切吗?

时间:2015-11-21 14:02:51

标签: java generics lambda

在Java中,有没有办法声明可以提供给任何需要特定消费者的方法的消费者?

我会试着说明一下:

A createA(String someVar, Consumer<ThingAConfig> configLambda);
B createB(String someVar, Consumer<ThingBConfig> configLambda);

Consumer<?> NO_CONFIG = c -> {}

createA("", NO_CONFIG);  // does not work, "argument mismatch"
createB("", NO_CONFIG);  // does not work, "argument mismatch"

有一点可行,就是制作一个原始的消费者:

Consumer RAW_NO_CONFIG = c -> {}

但是在使用后你会得到“未经检查的转换”。

createA("", RAW_NO_CONFIG);  // "works" with "unchecked conversion"
createB("", RAW_NO_CONFIG);  // "works" with "unchecked conversion"

似乎太严格了,不能做出类似的东西,因为我有很多理由要求消费者可以吃任何东西。

3 个答案:

答案 0 :(得分:4)

问题在于createA()createB()的签名。他们应该

A createA(String someVar, Consumer<? super ThingAConfig> configLambda);

这样,您就可以传递Consumer<ThingAConfig>Consumer<Object>(可以吃任何东西),或{{1的任何超类或超级接口的消费者}}

如果您坚持使用ThingAConfig作为参数类型,那么您唯一可以传递的是Consumer<ThingAConfig>

答案 1 :(得分:2)

另一种解决方法是调用这样的方法来获得所需类型的消费者:

public static <T> Consumer<T> emptyConsumer(){
    return t -> {};
}
...
createA("", emptyConsumer());

//Of course you could also just do this in this case:
createA("", c -> {});

或者,如果您可以等待Java 10,则会打开JEP,这将允许接口或类的创建者为您指定通配符,因此您的方法将等同于{{3 }}

答案 2 :(得分:0)

有两种方法可以做到这一点

A createA(String someVar, Consumer<?> configLambda)

消费者可以接受任何类型。我们可以通过以下方式将其限制在一定程度

A createA(String someVar, Consumer<? extends ParentType> configLambda)
//meaning passed type should be ParentType or child of ParentType

A createA(String someVar, Consumer<? super ChildType> configLambda)
//meaning passed type should be ChildType or some parent of ChildType

另一种方法是

<T> A createA(String someVar, Consumer<T> configLambda)

在这种情况下它也可以接受任何类型,大多数时候Java应该能够通过传递的变量的类型来推断类型T,如果不是,你必须手动传递类型信息。 / p>

//without explicit type
myClassObj.createA("", new Consumer<SomeType>);

//with explicit type
myClassObj.<SomeType>createA("", new Consumer<SomeType>);