如果我想在不同状态下应用不同的操作,如何避免编译错误 "lambda expression should be final or effectively final"?
How can I avoid complie error "lambda expression should be final or effectively final", if I want to apply different actions under different state?
例如我有两个尽可能简单的类,A和B
我想对 B 的对象采取一些操作,如果 A 对象的某些特定字段发生变化,我应该做一件事,如果其他字段发生变化,我应该做第二件事,我如何使用 Lambda 做到这一点?
答:
public class A {
private int someField;
private String nextField;
public A(int someField, String nextField) {
this.someField = someField;
this.nextField = nextField;
}
public int getSomeField() {
return someField;
}
public void setSomeField(int someField) {
this.someField = someField;
}
public String getNextField() {
return nextField;
}
public void setNextField(String nextField) {
this.nextField = nextField;
}
}
乙:
public class B {
private String someField;
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
public B(String someField) {
this.someField = someField;
}
}
演示:
public class Demo {
public static <T> boolean isFieldChanged(T oldValue, T newValue) {
return !Objects.equals(oldValue, newValue);
}
public static void someActionOne(B test){
return;
}
public static void someActionTwo(B test){
return;
}
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
Consumer<B> action = null;
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
action = Demo::someActionOne;
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
action = Demo::someActionTwo;
}
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
mockData.forEach(b -> action.accept(b));
}
}
在那种情况下如何避免编译错误?
要成为effectively-final,变量在初始化后不得更改。
如果你想使用不同的动作,只需将它们初始化两次:
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
mockData.forEach(Demo::someActionOne);
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
mockData.forEach(Demo::someActionTwo);
}
}
例如我有两个尽可能简单的类,A和B 我想对 B 的对象采取一些操作,如果 A 对象的某些特定字段发生变化,我应该做一件事,如果其他字段发生变化,我应该做第二件事,我如何使用 Lambda 做到这一点?
答:
public class A {
private int someField;
private String nextField;
public A(int someField, String nextField) {
this.someField = someField;
this.nextField = nextField;
}
public int getSomeField() {
return someField;
}
public void setSomeField(int someField) {
this.someField = someField;
}
public String getNextField() {
return nextField;
}
public void setNextField(String nextField) {
this.nextField = nextField;
}
}
乙:
public class B {
private String someField;
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
public B(String someField) {
this.someField = someField;
}
}
演示:
public class Demo {
public static <T> boolean isFieldChanged(T oldValue, T newValue) {
return !Objects.equals(oldValue, newValue);
}
public static void someActionOne(B test){
return;
}
public static void someActionTwo(B test){
return;
}
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
Consumer<B> action = null;
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
action = Demo::someActionOne;
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
action = Demo::someActionTwo;
}
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
mockData.forEach(b -> action.accept(b));
}
}
在那种情况下如何避免编译错误?
要成为effectively-final,变量在初始化后不得更改。
如果你想使用不同的动作,只需将它们初始化两次:
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
mockData.forEach(Demo::someActionOne);
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
mockData.forEach(Demo::someActionTwo);
}
}