在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"
似乎太严格了,不能做出类似的东西,因为我有很多理由要求消费者可以吃任何东西。
答案 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>);