我正在编写一个应该描述外卖系统的程序。我有一个特定的方法,用来模拟客户是否有足够的钱来使用界面购买东西。我遇到的问题是,当我试图实现一个接口,userinputretriiever,使用lambda..我只能使用lambda表达式中的最终变量。当它开始为方法本身shouldSimulate()创建返回语句时,我意识到我不能,因为我返回的内容只在lambda中可见。现在IntelliJ,建议使用一个最终数组,因为我可以在lambda表达式内外使用它。我只需要理解为什么使用数组工作,而不是使用变量。你能解释一下吗?
方法如下:
public boolean shouldSimulate() {
boolean[] hasMoney = new boolean[1];
String userPrompt = """
Please choose an option from the following:
0. To end simulation process
1. To proceed with simulation process""";
UserInputRetriever<?> intUserInputRetriever = selection -> {
if(selection == 1 && customer.money >= menu.getLowestFoodCost()){
System.out.println("You have enough money.nProceeding with " +
"simulation");
hasMoney[0] = true;
}
else if (selection == 1 && customer.money < menu.getLowestFoodCost()){
System.out.println("You do not have enough money.nEnding the" +
" simulation");
hasMoney[0] = false;
}
else if(selection == 0){
System.out.println("Terminating simulation");
hasMoney[0] = false;
}
else
throw new IllegalArgumentException("Please choose a valid " +
"option");
return hasMoney[0];// if hasMoney was a variable, this would not throw a compile time error
};
getOutputOnInput(userPrompt, intUserInputRetriever);// you can ignore this line
return hasMoney[0];// if hasMoney was a variable, this would throw a compile time error
}
我尝试在本地首先使用变量,并尝试在我的接口实现(使用lambda)中也使用它,但它抛出错误。但在使用IntelliJ的建议后,它建议使用数组,它工作了。我想知道为什么
Java Lang。规范声明"对有效最终变量的限制"禁止访问动态更改的局部变量,捕获这些局部变量可能会引入并发问题。
为了解决这个问题,你可以使用原子引用或原子类型,例如AtomicBoolean。
顺便说一句:提供一个问题和解决方案的可执行示例对其他人是有帮助的。这样可以使帮助更容易:
import org.junit.jupiter.api.Test;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.jupiter.api.Assertions.*;
public class FunctionalInterfaceProblem {
public static String EXCEPTION_MESSAGE = "Value not 0 or 1";
@java.lang.FunctionalInterface
interface SomeInterfaceWithBoolean<T> {
boolean calculate(T i) throws IllegalArgumentException;
}
@Test
public void testWihArray() {
boolean[] outcome = new boolean[1];
SomeInterfaceWithBoolean<Integer> result = i -> {
if(i == 1){
outcome[0] = true;
} else if (i == 0){
outcome[0] = false;
} else {
throw new IllegalArgumentException(EXCEPTION_MESSAGE);
}
return outcome[0];
};
assertFalse(result.calculate(0));
assertTrue(result.calculate(1));
Throwable exception = assertThrows(IllegalArgumentException.class, ()->{result.calculate(2);} );
assertEquals(EXCEPTION_MESSAGE, exception.getMessage());
}
@java.lang.FunctionalInterface
interface SomeInterfaceWithAtomicBoolean<T> {
AtomicBoolean calculate(T i) throws IllegalArgumentException;
}
@Test
public void testWihAtomicBoolean() {
AtomicBoolean outcome = new AtomicBoolean(false);
SomeInterfaceWithAtomicBoolean<Integer> result = i -> {
if(i == 1){
outcome.set(true);
} else if (i == 0){
outcome.set(false);
} else {
throw new IllegalArgumentException(EXCEPTION_MESSAGE);
}
return outcome;
};
assertFalse(result.calculate(0).get());
assertTrue(result.calculate(1).get());
Throwable exception = assertThrows(IllegalArgumentException.class, ()->{result.calculate(2);} );
assertEquals(EXCEPTION_MESSAGE, exception.getMessage());
}
}