简体   繁体   English

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

[英]local variables must be final or effectively final

I have an async operation inside of Java 8 which return an onError callback or an onSuccess callback. 我在Java 8中有一个异步操作,该操作返回onError回调或onSuccess回调。 I need to return inside of my method if the operation was a success or not. 如果操作成功或失败,我需要返回方法内部。 So I am returning a boolean to state this information. 因此,我返回一个布尔值来声明此信息。 The problem I am facing is I get the following compilation error: 我面临的问题是出现以下编译错误:

error: local variables referenced from an inner class must be final or effectively final 错误:从内部类引用的局部变量必须是final或有效的final

Googling the error I can see you this type of operation is not allowed, but then how can I return if the operation was a success or not? 谷歌搜索错误,我可以看到您不允许这种类型的操作,但是如果操作成功或失败,如何返回?

 public Boolean addUser(String email, String password) {

    Boolean isSuccess = false;

    Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
    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;

}

First I will explain what the error message means, then I will tell you what is wrong with your design and suggest what to do. 首先,我将解释错误消息的含义,然后,我将告诉您您的设计出了什么问题并提出建议。

First, the error message. 首先,错误消息。 isSuccess is a local variable, that is, as soon as the method addUser finishes, it is gone. isSuccess是局部变量,即方法addUser完成,它就会消失。 However, the AsyncHandler instance you create might live longer than that. 但是,您创建的AsyncHandler实例的AsyncHandler可能会更长。 If it does, it would refer to a variable which doesn't exist anymore. 如果是这样,它将引用一个已不存在的变量。

This would not be a problem if the variable were final or effectively final. 如果变量是final或有效地为final,这将不是问题。 Then we would know that the variable will never change, so we could just copy the variable to the newly created object and refer to that copy. 然后,我们将知道该变量将永远不会更改,因此我们只需将变量复制到新创建的对象并引用该副本即可。 Note that in case of a reference variable, it is the reference that doesn't change, the object it refers to might still be modified. 注意,在引用变量的情况下,引用不变, 引用的对象可能仍会被修改。

To circumvent this problem, the creators of Java have decided that from an anonymous inner class (or a lambda expression) you cannot refer to a local variable that is not final (or effectively final). 为了解决此问题,Java的创建者已决定,从匿名内部类(或lambda表达式)中,您不能引用不是最终(或有效地是最终)的局部变量。 The error message tells you that you're doing exactly that. 该错误消息告诉您您正在执行此操作。

So now to your design. 现在开始设计。 Your design cannot work in this way. 您的设计无法以这种方式工作。 The AsyncHandler instance will probably live until after the method finishes. 该方法完成之前, AsyncHandler实例可能一直存在。 Its methods will be probably executed in a different thread, so it's likely that its methods are called after your addUser method finishes. 它的方法可能在不同的线程中执行,因此很可能在addUser方法完成后调用了它的方法。 So what should addUser return? 那么addUser应该返回什么? At the moment that it finishes, it might not even know whether the operation was successful not! 在完成时,它甚至可能不知道操作是否成功!

You perform an operation asynchronously , that is, on a different thread. 异步执行操作,即在另一个线程上执行。 This operation might take 1 millisecond, or 1 minute, or even 10 years. 此操作可能需要1毫秒或1分钟,甚至10年。 If you want to see if that operation was successful, you must somehow communicate its result to the thread that executes addUser . 如果要查看该操作是否成功,则必须以某种方式将其结果传递给执行addUser的线程。

Inter-thread communication is not a trivial task, but you're lucky: the putItemAsync returns a Future instance, and the Future class is intended for exactly what you want to do: find out if an asynchronous operation has finished and obtain its result. 线程间通信不是一件putItemAsync ,但是您很幸运: putItemAsync返回一个Future实例,而Future类正是用于您想要做的事情:找出异步操作是否已完成并获得其结果。

To check whether the asynchronous operation has finished, poll the isDone() method of the returned Future . 要检查异步操作是否已完成,请轮询返回的FutureisDone()方法。 If it finished, you can obtain the result of the operation by calling the get() method of the Future . 如果完成,则可以通过调用Futureget()方法get()操作结果。 If the operation was aborted abnormally because it threw an exception, get() will throw an ExecutionException whose getCause() is the thrown exception. 如果该操作由于引发异常而异常中止,则get()将引发ExecutionExceptiongetCause()是引发的异常。

Or, of course, you decide to run the operation synchronously (on the same thread) using the putItem method. 或者,当然,您决定使用putItem方法同步运行操作(在同一线程上)。 Then your method will wait for the operation to finish and you have the result immediately. 然后,您的方法将等待操作完成,您将立即获得结果。

This is not a good practice and also, it might not work. 这不是一个好习惯,也可能不起作用。 In your code, new AsyncHandler() will be running in a separate thread. 在您的代码中, new AsyncHandler()将在单独的线程中运行。 Since it's not a blocking call, main thread will not wait for it's completion. 由于这不是阻塞调用,因此主线程将不等待其完成。

So, what will happen is, just after calling dynamoDB.putItemAsync(...) , the return statement will get executed even before your AsyncHandler() finishes it's execution and changes the value of isSuccess . 因此,将发生什么,就在调用dynamoDB.putItemAsync(...) ,即使在AsyncHandler()完成执行并更改isSuccess的值之前,return语句也会被执行。 That means, return isSuccess; 这意味着return isSuccess; might return the default value false . 可能返回默认值false

Note: If you really want to do it this way, you can make the boolean variable as a field variable. 注意:如果您确实想这样做,可以将布尔变量设为字段变量。

public boolean isSuccess = false;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 内部类引用的局部变量必须是最终变量或有效最终变量 - Local variables referred from inner class must be final or effectively final 从 lambda 表达式引用的局部变量必须是最终的或有效的最终变量 - local variables referenced from a lambda expression must be final or effectively final 内部类的局部变量必须是最终变量或有效最终变量 - Local variables from a inner class must be final or effectively final 从内部类引用的局部变量必须是最终的或有效的最终 - local variables referenced from an inner class must be final or effectively final JSlider和JTextField数组更改侦听器-从内部类引用的局部变量必须是最终的或实际上是最终的 - JSlider and JTextField array change listener - Local variables referenced from inner class must be final or effectively final 可运行的“从内部类引用的局部变量中的计数器必须是最终的或有效地是最终的” - counter in runnable 'local variables referenced from an inner class must be final or effectively final' 从内部类引用的Java MultiThreadding局部变量必须是有效final的final - Java MultiThreadding Local variables referenced from an inner class must be final of effectively final 如何解决“来自内部类的局部变量引用必须是有效的final的final”? - How to solve “local variables references from an inner class must be final of effectively final”? 错误:从内部类引用的局部变量必须是final或有效的final - error: local variables referenced from an inner class must be final or effectively final 从内部类引用的JAVA局部变量必须是final或有效的final - JAVA local variables referenced from an inner class must be final or effectively final
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM