如何解决带有可变参数的函数式接口
我正在尝试创建一个可以接受可变数量参数的函数式接口。
我的界面是:
public interface Callback {
void call(Object... args);
}
我尝试给出如下实现:
Callback toggleInfoPanel = () -> {
boolean isVisible = infoPanel.isVisible();
infoPanel.setVisible( !isVisible );
};
但它要求我有一个参数。为什么?我以为我可以传递任意数量的参数,那为什么我不能不带参数地使用它呢?
解决方法
说明
您的实现现在接受零参数。但是接口明确声明能够接受任何参数。
因此您的实现必须能够接受任何参数。
但它要求我有一个参数。为什么?我以为我可以传递任意数量的参数,那为什么我不能不带参数地使用它呢?
您似乎将上述接口的实现声明与实际调用站点混淆了。该方法支持无参数调用是正确的。但它还必须支持使用任何其他数量的参数进行调用。
所以虽然调用它没有像
这样的参数是完全可以的toggleInfoPanel.call();
它还必须能够支持使用不同的参数集调用
toggleInfoPanel("hello",2);
解决方案
您必须在 lambda 中使用 Object[]
。那是因为 Java 使用隐式数组来实现可变参数。所以Object... args
或多或少衰减到Object[] args
。
Callback toggleInfoPanel = args -> {
boolean isVisible = infoPanel.isVisible();
infoPanel.setVisible(!isVisible);
};
所以有人可以这样做
toggleInfoPanel.call("hello",23,"world","test",2.34);
是否要解释 args
取决于您。
注意事项
Java 已经提供了一个能够做你想做的事情的接口,在上面有额外的类型安全。它被称为Consumer
。
一个也可以接受任意输入的例子:
Consumer<Object[]> toggleInfoPanel = args -> {
boolean isVisible = infoPanel.isVisible();
infoPanel.setVisible(!isVisible);
};
和呼叫站点:
Object[] args = { "hello",2.34 };
toggleInfoPanel.accept(args);
很酷的事情是这可以提供类型安全。比如说,你只想接受一个 String
,你可以这样做:
Consumer<String> printer = text -> System.out.println(text);
// or in short just: System.out::println
如果您不小心称错了,您现在将获得编译时安全性:
printer.accept(5); // not a String!
关于这一点,如果您不想接受任何参数,则还有 Runnable
,如果您明确想要接受两个参数,则还有 BiConsumer
。
对于其他任何事情,最好将您的参数包装到一个专用的单个类中,而不是提供 5 个参数。所以,而不是:
Consumer<Object[]> consumer = ...
consumer.accept(new Object[] { "John",20 });
更喜欢创建一个 Person
类,然后使用 Consumer<Person>
:
Consumer<Person> consumer = ...
consumer.accept(new Person("John",20));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。