局部变量必须是最终的或有效的最终

我在Java 8中有一个异步操作,它返回一个onError回调或onSuccess回调。 如果操作成功与否,我需要返回我的方法。 所以我返回一个布尔值来说明这个信息。 我面临的问题是我得到以下编译错误:

错误:从内部类引用的局部变量必须是最终的或有效的最终

谷歌搜索错误我可以看到你不允许这种类型的操作,但如果操作成功与否,我怎么能返回?

public Boolean addUser(String email, String password) { Boolean isSuccess = false; Map item = new HashMap(); item.put("email", new AttributeValue(email)); //email item.put("password", new AttributeValue(password)); //password dynamoDB.putItemAsync(new PutItemRequest().withTableName("Users").withItem(item), new AsyncHandler() { @Override public void onError(Exception excptn) { } @Override public void onSuccess(AmazonWebServiceRequest rqst, Object result) { isSuccess = true; } }); return isSuccess; } 

这不是一个好习惯,也可能不起作用。 在您的代码中, new AsyncHandler()将在一个单独的线程中运行。 由于它不是阻塞调用,因此主线程不会等待它完成。

因此,在调用dynamoDB.putItemAsync(...) ,即使在AsyncHandler()完成执行并更改isSuccess的值之前,也会执行return语句。 这意味着, return isSuccess; 可能会返回默认值false

注意:如果您真的想这样做,可以将布尔变量作为字段变量。

 public boolean isSuccess = false; 

首先,我将解释错误消息的含义,然后我会告诉您设计有什么问题,并建议做什么。

首先是错误消息。 isSuccess是一个局部变量,也就是说,一旦addUser方法完成,它就消失了。 但是,您创建的AsyncHandler实例可能比这更长。 如果是,它将引用一个不再存在的变量。

如果变量是最终的或有效的最终变量,这不会成为问题。 然后我们就知道变量永远不会改变,所以我们可以将变量复制到新创建的对象并引用该副本。 请注意,对于引用变量,它是不会更改的引用 ,它引用的对象可能仍会被修改。

为了解决这个问题,Java的创建者已经决定从匿名内部类(或lambda表达式)中不能引用非最终(或有效最终)的局部变量。 错误消息告诉您正是这样做的。

所以现在你的设计。 您的设计无法以这种方式工作。 AsyncHandler实例可能会一直存在,直到方法完成。 它的方法可能会在不同的线程中执行,因此很可能在addUser方法完成后调用其方法。 那么addUser应该返回什么? 在它完成的那一刻,它甚至可能不知道操作是否成功!

您可以异步执行操作,即在不同的线程上执行操作。 此操作可能需要1毫秒,或1分钟,甚至10年。 如果要查看该操作是否成功,则必须以某种方式将其结果传递给执行addUser的线程。

线程间通信不是一项简单的任务,但是你很幸运: putItemAsync返回一个Future实例,而Future类的目的正是你要做的事情:找出异步操作是否已经完成并获得结果。

要检查异步操作是否已完成,请轮询返回的FutureisDone()方法。 如果完成,您可以通过调用Futureget()方法get()操作的结果。 如果操作由于抛出exception而exception中止,则get()将抛出ExecutionExceptiongetCause()是抛出的exception。

或者,当然,您决定使用putItem方法同步(在同一个线程上)运行操作。 然后你的方法将等待操作完成,你立即得到结果。