在 Java 8 中分配多个 JCheckBox 侦听器的冗余方式较少? (例如方法参考?)
Less redundant way to assign several JCheckBox listeners in Java 8? (E.g. method reference?)
模式总是一样的:
- 向 JCheckBox 添加新的 ActionListener X。监听器的 body 这样做:
- 获得objectY参考。如果引用 !=null,请执行以下操作:
- 在 Y 上使用参数 X.isSelected()
调用方法 Z
示例代码:
jChecKBoxWindowSizeLocked.addActionListener(e -> {
final WindowConfig lastWin = getLastTouchedWindowConfig();
if (lastWin != null) {
lastWin.setSizeLocked(jChecKBoxWindowSizeLocked.isSelected());
}
});
jChecKBoxRememberSize.addActionListener(e -> {
final WindowConfig lastWin = getLastTouchedWindowConfig();
if (lastWin != null) {
lastWin.setRememberSize(jChecKBoxRememberSize.isSelected());
}
});
etc.
这看起来非常多余,好像它应该可以用 Lambda 或方法解决,但是我如何在没有确定 object Y 的情况下提供对方法 Z 的引用?我试过这个方法,但我使用的调用可能不正确:
private void addCheckboxListener(final JCheckBox checkBox, final Consumer<Boolean> setter) {
checkBox.addActionListener(e -> {
if (setter != null) {
setter.accept(checkBox.isSelected());
}
});
}
来电是:
addCheckboxListener(cbRememberSize, getLastTouchedWindowConfig()::setRememberSize);
我很确定这会在调用 add 方法时提供对 getter returns 的任何引用,而不是稍后解析的一般引用。因此,这会在其自己的行中导致 NullPointerException(但编译得很好):
addCheckboxListener(cbRememberLocation, ((WindowConfig) null)::setRememberLocation);
当然,我可以只给出通过反射声明的目标 class' setter 方法,但是对于大约 10 个 JCheckBoxes 来说,这完全是矫枉过正。现在,如果它只是大约 10,那么我应该只是复制代码而不是扮演科学家,对吧。
但是我的 point/question 认为应该有某种 Lambda-ish method-reference-y 的方法来完成这项工作。还是这种可能性确实不存在?
编辑
感谢 Holger 的回复,我现在成功地尝试使用具有附加实例参数的静态 setters,这样 addCheckboxListener 就可以采用 static 方法引用因此按预期工作。 (EDIT2: 不。不是静态的。请参阅对 Holger(已接受)回复的评论。"EDIT" 部分的其余部分是在此 EDIT2 之前编写的。)
我不乐意让 setters 静态化,但目前这似乎是最优雅的解决方案,而且它肯定是一把放在工具棚里的好刀。
一个新的problem/question由此产生。在我可能就此发表新的 post 之前,我会在这里提问:
本次调用出现无法解释的编译错误:
addCheckboxListener(jCheckBoxRememberLocation, WindowConfig::setRememberLocation);
方法的头部:
private void addCheckboxListener(JCheckBox checkBox, BiConsumer<WindowConfig, Boolean> setter) {
错误:
Error:(72, 49) java: incompatible types: invalid method reference
reference to setRememberLocation is ambiguous
both method setRememberLocation(WindowConfig,Boolean) in WindowConfig and method setRememberLocation(boolean) in WindowConfig match
只有当我在 WinConfig class 中同时拥有旧的 non-static setter 和新的静态 setter 时才会出现错误,而且它们都需要有一组不同的参数。 这可能是 Java 错误吗? 以下是方法:
public void setRememberLocation(final boolean rememberLocation) {
this.rememberLocation = rememberLocation;
}
public static void setRememberLocation(final WindowConfig instance, final Boolean rememberLocation) {
instance.rememberLocation = rememberLocation;
}
错误似乎是错误的,因为两种方法中只有一种符合配置文件。
真正奇怪的是:如果我将 non-static 方法的头部更改为与静态方法的头部完全相同,错误就会消失。
但是 REALLY 超级奇怪的是:如果我然后交换 non-static 方法的第一个和第二个参数,错误仍然不会发生。 WTF!?
C:\>java -version
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
C:\Program Files\Java\jdk1.8.0_74\bin>javac -version
javac 1.8.0_74
winver
Windows 7 Ultimate
Version 6.1 (Build 7601: Service Pack 1)
项目使用了 Java 版本。它也是我系统上唯一的一个。 (不,其他地方也没有 32 位版本。)
显然你想要这样的方法:
private void addCheckboxListener(
JCheckBox checkBox, BiConsumer<WindowConfig, Boolean> setter) {
Objects.requireNonNull(setter);
checkBox.addActionListener(e -> {
final WindowConfig lastWin = getLastTouchedWindowConfig();
if(lastWin != null) {
setter.accept(lastWin, checkBox.isSelected());
}
});
}
您可以将其调用为
addCheckboxListener(cbRememberSize, WindowConfig::setRememberSize);
addCheckboxListener(cbRememberLocation, WindowConfig::setRememberLocation);
应该在其上调用该方法的 WindowConfig
实例成为功能签名的一部分,并将在事件发生时获取并传递给该功能。
请注意,我将行为更改为立即拒绝 null
setter 参数,而不是默默地忽略此类错误条件。
模式总是一样的:
- 向 JCheckBox 添加新的 ActionListener X。监听器的 body 这样做:
- 获得objectY参考。如果引用 !=null,请执行以下操作:
- 在 Y 上使用参数 X.isSelected() 调用方法 Z
示例代码:
jChecKBoxWindowSizeLocked.addActionListener(e -> {
final WindowConfig lastWin = getLastTouchedWindowConfig();
if (lastWin != null) {
lastWin.setSizeLocked(jChecKBoxWindowSizeLocked.isSelected());
}
});
jChecKBoxRememberSize.addActionListener(e -> {
final WindowConfig lastWin = getLastTouchedWindowConfig();
if (lastWin != null) {
lastWin.setRememberSize(jChecKBoxRememberSize.isSelected());
}
});
etc.
这看起来非常多余,好像它应该可以用 Lambda 或方法解决,但是我如何在没有确定 object Y 的情况下提供对方法 Z 的引用?我试过这个方法,但我使用的调用可能不正确:
private void addCheckboxListener(final JCheckBox checkBox, final Consumer<Boolean> setter) {
checkBox.addActionListener(e -> {
if (setter != null) {
setter.accept(checkBox.isSelected());
}
});
}
来电是:
addCheckboxListener(cbRememberSize, getLastTouchedWindowConfig()::setRememberSize);
我很确定这会在调用 add 方法时提供对 getter returns 的任何引用,而不是稍后解析的一般引用。因此,这会在其自己的行中导致 NullPointerException(但编译得很好):
addCheckboxListener(cbRememberLocation, ((WindowConfig) null)::setRememberLocation);
当然,我可以只给出通过反射声明的目标 class' setter 方法,但是对于大约 10 个 JCheckBoxes 来说,这完全是矫枉过正。现在,如果它只是大约 10,那么我应该只是复制代码而不是扮演科学家,对吧。
但是我的 point/question 认为应该有某种 Lambda-ish method-reference-y 的方法来完成这项工作。还是这种可能性确实不存在?
编辑
感谢 Holger 的回复,我现在成功地尝试使用具有附加实例参数的静态 setters,这样 addCheckboxListener 就可以采用 static 方法引用因此按预期工作。 (EDIT2: 不。不是静态的。请参阅对 Holger(已接受)回复的评论。"EDIT" 部分的其余部分是在此 EDIT2 之前编写的。)
我不乐意让 setters 静态化,但目前这似乎是最优雅的解决方案,而且它肯定是一把放在工具棚里的好刀。
一个新的problem/question由此产生。在我可能就此发表新的 post 之前,我会在这里提问:
本次调用出现无法解释的编译错误:
addCheckboxListener(jCheckBoxRememberLocation, WindowConfig::setRememberLocation);
方法的头部:
private void addCheckboxListener(JCheckBox checkBox, BiConsumer<WindowConfig, Boolean> setter) {
错误:
Error:(72, 49) java: incompatible types: invalid method reference
reference to setRememberLocation is ambiguous
both method setRememberLocation(WindowConfig,Boolean) in WindowConfig and method setRememberLocation(boolean) in WindowConfig match
只有当我在 WinConfig class 中同时拥有旧的 non-static setter 和新的静态 setter 时才会出现错误,而且它们都需要有一组不同的参数。 这可能是 Java 错误吗? 以下是方法:
public void setRememberLocation(final boolean rememberLocation) {
this.rememberLocation = rememberLocation;
}
public static void setRememberLocation(final WindowConfig instance, final Boolean rememberLocation) {
instance.rememberLocation = rememberLocation;
}
错误似乎是错误的,因为两种方法中只有一种符合配置文件。
真正奇怪的是:如果我将 non-static 方法的头部更改为与静态方法的头部完全相同,错误就会消失。
但是 REALLY 超级奇怪的是:如果我然后交换 non-static 方法的第一个和第二个参数,错误仍然不会发生。 WTF!?
C:\>java -version
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
C:\Program Files\Java\jdk1.8.0_74\bin>javac -version
javac 1.8.0_74
winver
Windows 7 Ultimate
Version 6.1 (Build 7601: Service Pack 1)
项目使用了 Java 版本。它也是我系统上唯一的一个。 (不,其他地方也没有 32 位版本。)
显然你想要这样的方法:
private void addCheckboxListener(
JCheckBox checkBox, BiConsumer<WindowConfig, Boolean> setter) {
Objects.requireNonNull(setter);
checkBox.addActionListener(e -> {
final WindowConfig lastWin = getLastTouchedWindowConfig();
if(lastWin != null) {
setter.accept(lastWin, checkBox.isSelected());
}
});
}
您可以将其调用为
addCheckboxListener(cbRememberSize, WindowConfig::setRememberSize);
addCheckboxListener(cbRememberLocation, WindowConfig::setRememberLocation);
应该在其上调用该方法的 WindowConfig
实例成为功能签名的一部分,并将在事件发生时获取并传递给该功能。
请注意,我将行为更改为立即拒绝 null
setter 参数,而不是默默地忽略此类错误条件。