Runnable Inline Class声明 - 能够访问外部非final变量

时间:2014-03-21 03:12:48

标签: java anonymous-inner-class

在下面的代码中,我想知道为什么内联类中的run()能够访问外部类变量 - 信号量(即使它没有声明为final)。

    private Semaphore semaphore = new Semaphore(bufferSize);

    private Runnable producerRunnable = new Runnable(){

        @Override
        public void run()
        {
            try
            {
                semaphore.acquire();
            }
            catch(InterruptedException e)
            {
                System.out.println("producer was interrupted while trying to acquire semaphore");                   
            }
        }
   };

我希望Eclipse标记编译错误 - 因为信号量引用未声明为最终

2 个答案:

答案 0 :(得分:2)

这很正常。最终要求仅描述为适用于局部变量和参数(JLS):

  

使用但未在内部类中声明的任何局部变量,形式参数或异常参数必须声明为final [...]。

封闭实例的成员不需要最终访问它们。

答案 1 :(得分:0)

因为您已将信号量定义为该类的全局变量,并且如果要在runnable中访问它,则应将所有局部变量声明为final。

public class KamalTest {

    /**
     * @param args the command line arguments
     */
    private Semaphore semaphore = new Semaphore(2);
    private Runnable producerRunnable = new Runnable() {
        @Override
        public void run() {
            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                System.out.println("producer was interrupted while trying to acquire semaphore");
            }
        }
    };

    public void startThread1() {
        Thread th = new Thread(producerRunnable);
        th.start();
    }

    public void startThread2() {
        final Semaphore semPhore = new Semaphore(2);

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    semPhore.acquire();
                } catch (InterruptedException ex) {
                    Logger.getLogger(KamalTest.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };


        Thread th = new Thread(runnable);
        th.start();
    }

    public static void main(String[] args) {

        KamalTest kt = new KamalTest();
        kt.startThread1();


        System.out.println("Internet Available : " + isInternetAvailable());

    }
}


}