Cannot refer to a non-final variable inside an inner class defined in a different method

前端 未结 20 2199
一向
一向 2020-11-21 05:04

Edited: I need to change the values of several variables as they run several times thorugh a timer. I need to keep updating the values with every iteration through the timer

相关标签:
20条回答
  • 2020-11-21 05:25

    If you want to change a value in a method call within an anonymous class, that "value" is actually a Future. So, if you use Guava, you can write

    ...
    final SettableFuture<Integer> myvalue = SettableFuture<Integer>.create();
    ...
    someclass.run(new Runnable(){
    
        public void run(){
            ...
            myvalue.set(value);
            ...
        }
     }
    
     return myvalue.get();
    
    0 讨论(0)
  • 2020-11-21 05:29

    you can just declare the variable outside the outer class. After this, you will be able to edit the variable from within the inner class. I sometimes face similar problems while coding in android so I declare the variable as global and it works for me.

    0 讨论(0)
  • 2020-11-21 05:29

    To solve the problem above, different languages make different decisions.

    for Java, the solution is as what we see in this article.

    for C#, the solution is allow side-effects and capture by reference is the only option.

    for C++11, the solution is to allow the programmer make the decision. They can choose to capture by value or by reference. If capturing by value, no side-effects would occur because the variable referenced is actually different. If capture by reference, side-effects may occur but the programmer should realize it.

    0 讨论(0)
  • 2020-11-21 05:29

    Because it's confusing if the variable isn't final, as the changes to it won't be picked up in the anonymous class.

    Just make the variables 'price' and 'lastPrice' final.

    -- Edit

    Oops, and you'll also need to not assign to them, obviously, in your function. You'll need new local variables. Anyway, I suspect someone has given you a better answer by now.

    0 讨论(0)
  • 2020-11-21 05:37

    what worked for me is just define the variable outside this function of your.

    Just before main function declare i.e.

    Double price;
    public static void main(String []args(){
    --------
    --------
    }
    
    0 讨论(0)
  • 2020-11-21 05:39

    Java doesn't support true closures, even though using an anonymous class like you are using here (new TimerTask() { ... }) looks like a kind of closure.

    edit - See the comments below - the following is not a correct explanation, as KeeperOfTheSoul points out.

    This is why it doesn't work:

    The variables lastPrice and price are local variables in the main() method. The object that you create with the anonymous class might last until after the main() method returns.

    When the main() method returns, local variables (such as lastPrice and price) will be cleaned up from the stack, so they won't exist anymore after main() returns.

    But the anonymous class object references these variables. Things would go horribly wrong if the anonymous class object tries to access the variables after they have been cleaned up.

    By making lastPrice and price final, they are not really variables anymore, but constants. The compiler can then just replace the use of lastPrice and price in the anonymous class with the values of the constants (at compile time, of course), and you won't have the problem with accessing non-existent variables anymore.

    Other programming languages that do support closures do it by treating those variables specially - by making sure they don't get destroyed when the method ends, so that the closure can still access the variables.

    @Ankur: You could do this:

    public static void main(String args[]) {
        int period = 2000;
        int delay = 2000;
    
        Timer timer = new Timer();
    
        timer.scheduleAtFixedRate(new TimerTask() {
            // Variables as member variables instead of local variables in main()
            private double lastPrice = 0;
            private Price priceObject = new Price();
            private double price = 0;
    
            public void run() {
                price = priceObject.getNextPrice(lastPrice);
                System.out.println();
                lastPrice = price;
            }
        }, delay, period);      
    }
    
    0 讨论(0)
提交回复
热议问题