練習寫Swing的時候,遇到了一個問題,在匿名類別裡面使用外面的參數的時候,如果外面的參數不是final的,IDE會報錯:

local variable trgFileChooser is accessed from within inner class; needs to be declared final

程式碼如下:

JFileChooser trgFileChooser = new JFileChooser();
trgBrowser.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                int result = trgFileChooser.showDialog(null, null);
                if (result == JFileChooser.APPROVE_OPTION) {
                    File trgFile = trgFileChooser.getSelectedFile();
                    logic.setTrgFile(trgFile);
                    targetPath.setText(trgFile.getAbsolutePath());
                }
            }
        });



這當然只要把trgFileChooser改為final就好了:

final JFileChooser trgFileChooser = new JFileChooser();

擲筊問了Google大神,找到這篇討論,裡面提到這是JAVA API的規範,我們先來看JAVA API怎麼說的:

Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.

但是為什麼在匿名類別裡使用到的外部變數必須、一定是final的呢?

稍微拜了一下Google大神,當然又是找到Stackoverflow的討論串

懶得看問題了,直接看回答

When you create an instance of an anonymous inner class, any variables which are used within that class have their values copied in via the autogenerated constructor...

As the value has been copied into the instance of the anonymous inner class, it would look odd if the variable could be modified by the rest of the method - you could have code which appeared to be working with an out-of-date variable ...

 

裡面提到,當你建立一個匿名類別實體的時候,這個匿名類別內用到變數的值會在預設建構子中被複製過來,也就是說,匿名類別中用到的變數實際上跟外面的變數已經不是同一個變數了,這種做法的好處是,編譯器無須去管裡面跟外面的變數是否一樣。(C#就是直接抓外部變數,而不是複製值)

因為這樣的做法,所以如果這個變數是可變的話,那當外面的變數被更動的時候,裡面的值就會是舊的,相反的,若是變數在匿名類別裡面被更動,外面看到的值也不會是最新的。

...Basically it's a bit like communicating between one method and another: changes made to the parameters of one method aren't seen by its caller, but changes made to the objects referred to by the parameters are seen.

把這個變數設成final就解決了這個問題。如果真的想在匿名類別裡面更動,就要把該變數變成物件的形式,而非一般型別,因為物件的傳遞方式是傳址,也就是說雖然你不能把這個"物件的位址"指向另一個物件,但你可以改變"物件的內容"。

簡單來說就是把變數變成陣列、List之類的東西就可以啦~

 

arrow
arrow
    文章標籤
    java immutable anonymous class
    全站熱搜

    nnosnhoj 發表在 痞客邦 留言(0) 人氣()