为何匿名内部类只能访问final变量【转】

  是变量的做用域的问题,由于匿名内部类是出如今一个方法的内部的,若是它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final。由于虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或参数的做用域只在这个方法内部有效。由于编译的时候内部类和方法在同一级别上,因此方法中的变量或参数只有为final,内部类才能够引用。.net

Java代码: 
package com.cxz.j2se;   
  
public class MyClass {   
    public MyClass() {   
        final int finalValue = 10;   
        int not$Final = 20;   
        MyInterface myInterface = new MyInterface() {   
            public void functionWithoutPara() {   
                //compile Error   
                //System.out.println(noFinal);    
                System.out.println(finalValue);   
            }   
  
            public void functionWithPara(int num) {   
                System.out.println("The parameter " + num   
                        + " has been passed by the method");   
            }   
  
        };   
        myInterface.functionWithoutPara();   
        myInterface.functionWithPara(not$Final);   
        System.out.println(myInterface.getClass().getName());   
    }   
  
    public static void main(String[] args) {   
        new MyClass();   
  
    }   
  
线程

2、为何局部内部类只能访问final变量
  简单的来讲是做用域的问题。就好像方法外面作的事情并不能改变方法内才定义的变量,由于你并不知道方法里面这个时候已经存在了这个局部变量了没有。在这个内部类中方法里面的本地变量是失效的,也就是不在做用域内,因此是不可以访问的对象

  可是为何这里用final却又能够访问呢? 
  由于Java采用了一种copy   local   variable的方式来实现,也就是说把定义为final的局部变量拷贝过来用,而引用的也能够拿过来用,只是不能从新赋值。从而形成了能够access   local   variable的假象,而这个时候因为不能从新赋值,因此通常不会形成不可预料的事情发生blog

3、若是定义一个局部内部类,而且局部内部类使用了一个在其外部定义的对象,为何编译器会要求其参数引用是final呢?
注意:局部内部类,包括匿名内部类。递归

缘由以下:生命周期

abstract class ABSClass{
  public abstract void print();
}队列

public class Test2{
  public static void test(final String s){//一旦参数在匿名类内部使用,则必须是final
    ABSClass c=new ABSClass(){
      public void print(){
        System.out.println(s);
      }
    };
    c.print();
  }
  public static void main(String[] args){
    test("Hello World!");
  }
}进程

  JVM中每一个进程都会有多个根,每一个static变量,方法参数,局部变量,固然这都是指引用类型.基础类型是不能做为根的,根其实就是一个存储地址.垃圾回收器在工做时先从根开始遍历它引用的对象并标记它们,如此递归到最末梢,全部根都遍历后,没有被标记到的对象说明没有被引用,那么就是能够被回收的对象(有些对象有finalized方法,虽然没有引用,但JVM中有一个专门的队列引用它们直到finalized方法被执行后才从该队列中移除成为真正没有引用的对象,能够回收,这个与本主题讨论的无关,包括代的划分等之后再说明).这看起来很好.作用域

  可是在内部类的回调方法中,s既不多是静态变量,也不是方法中的临时变量,也不是方法参数,它不可能做为根,在内部类中也没有变量引用它,它的根在内部类外部的那个方法中,若是这时外面变量s重指向其它对象,则回调方法中的这个对象s就失去了引用,可能被回收,而因为内部类回调方法大多数在其它线程中执行,可能还要在回收后还会继续访问它.这将是什么结果?get

  而使用final修饰符不只会保持对象的引用不会改变,并且编译器还会持续维护这个对象在回调方法中的生命周期.因此这才是final变量和final参数的根本意义.

  文章出处:http://blog.csdn.net/onisland/article/details/5807637

相关文章
相关标签/搜索