簡體   English   中英

Java-如何從匿名內部類訪問非最終變量?

[英]Java - How am I accessing non final variables from an anonymous inner class?

如下面的代碼所示,我正在從ActionListener匿名內部類訪問JLabel。 這不會給我帶來任何錯誤,因此如何允許使用此方法,但是如果JLabel位於INSIDE,則在沒有final修飾符的情況下不允許使用該方法?

JLabel e = new JLabel("");
        public void myMethod() {

            JButton b = new JButton("ok");
            b.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    e.setSize(200,200);

                }

            });

        }

如果該變量在方法def內,則它是一個局部變量-並且您要實例化一個對象,該對象將在該方法執行后存在,並且該局部變量的生命周期已經結束(位於該方法的堆棧框架中)在方法返回時銷毀)。 為了使它完全起作用需要一些編譯器魔術,並且通常將其稱為閉包 ,即使其當前在Java中的實現如此la腳。 編譯器實際上將合成一個類,該類實現ActionListener並具有一個實例變量,該本地變量的值將被復制到該實例變量。

這是Java特有的限制,由於線程安全問題,您只能在final var上關閉。 這里的故事說,Java開發人員的直覺是,本地var始終是線程安全的-它不能在方法執行過程中進行更改(該方法未明確進行任何更改),可以如果沒有非Datavars,等等。如果您可以關閉非最終變量,則可能會違反該規則,因為該關閉可以與當前執行的方法並行執行並更改該變量。 這將導致一些非常違反直覺的行為。

但是,有一個(有些la腳)解決方法:

public void myMethod() {
    final JLabel[] e = {new JLabel("")};
    JButton b = new JButton("ok");
    b.addActionListener(new ActionListener() {
       @Override public void actionPerformed(ActionEvent arg0) {
         e[0].setSize(200,200);
    }});
}

e現在是一個單元素數組,它駐留在堆上,並且不會被方法的stackframe破壞。 您還可以憑直覺看到現在絕對不是線程安全的,並且偵聽器可以輕松地將e[0]的值更改為完全不同的值,並且此處顯示的方法將觀察到該更改,而無需使用顯式的突變代碼。它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM