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

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();   
  
    }   
  
}

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

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

三、如果定义一个局部内部类,并且局部内部类使用了一个在其外部定义的对象,为什么编译器会要求其参数引用是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就失去了引用,可能被回收,而由于内部类回调方法大多数在其它线程中执行,可能还要在回收后还会继续访问它.这将是什么结果?

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

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

为什么匿名内部类只能访问final变量【转】的更多相关文章

  1. Java 匿名内部类 只能访问final变量的原因

    文章来源:http://blog.sina.com.cn/s/blog_4b6f8d150100qni2.html 1)从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方 ...

  2. 匿名内部类和局部内部类只能访问final变量的原因

    以下是从各大网站找来的解释,我在这里摘抄一些从其他地方搬过来的大致思想,可能会比较乱, 详细解释 http://blog.csdn.net/salahg/article/details/7529091 ...

  3. 为什么匿名内部类和局部内部类只能访问final变量

    因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或 ...

  4. 为什么局部内部类和匿名内部类只能访问 final 的局部变量?

    首先,我们看一个局部内部类的例子: class OutClass { private int age = 12; public void outPrint(final int x) { class I ...

  5. 局部内部类为什么只能访问final局部变量,对于成员变量却可以随便访问?

    局部内部类为什么只能访问final局部变量,对于成员变量却可以随便访问? public class OuterClass { private int memberField = 10; public ...

  6. Java学习笔记23---内部类之局部内部类只能访问final的局部变量

    局部内部类是定义在方法体或代码块中的类,在笔记19中已有过简单介绍. 今天要讨论的是局部内部类为什么只能访问为常量的局部变量. 作者: 博客园--蝉蝉 请尊重作者劳动成果,转载请在标题注明“转载”字样 ...

  7. Java基础-内部类-为什么局部和匿名内部类只能访问局部final变量

    先看下面这段代码: public class Test { public static void main(String[] args) { } public void test(final int ...

  8. 匿名内部类中使用的外部局部变量为什么只能是final变量

    被匿名内部类引用的变量会被拷贝一份到内部类的环境中 但其后,在外部,该变量如果被修改,则内部外部不一致 Java为了避免数据不同步的问题,做出了匿名内部类只可以访问final的局部变量的限制. 究其原 ...

  9. 为什么匿名内部类只能访问其所在方法中的final类型的局部变量?

    大部分时候,类被定义成一个独立的程序单元.在某些情况下,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类. class Outer { priv ...

随机推荐

  1. 循序渐进Python3(十)-- 0 -- RabbitMQ

    RabbitMQ     RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息 ...

  2. java 访问mysql 实例

    前提条件: 1.安装eclipse,mysql.java jdk 2.安装mysql connect J  (我安装的版本是mysql connect J 5.1.39) 3.配置java环境变量 4 ...

  3. 浅谈Java 8的函数式编程

    函数式编程语言是什么? 函数式编程语言的核心是它以处理数据的方式处理代码.这意味着函数应该是第一等级(First-class)的值,并且能够被赋值给变量,传递给函数等等.(转载自http://xz.p ...

  4. 关于AFNetworking菊花转圈圈的问题

    刚开始接触AFN的时候,发现菊花老是不转,百度到大神的博客上,说AFN里面的API的网络加载菊花默认是关闭的(才发现默认情况下AFN的转圈圈的菊花是关闭的)需要手动打开才能够显示转圈圈,打开的方法是: ...

  5. (转)tar.xz文件如何解压

    XZ压缩最新压缩率之王 xz这个压缩可能很多都很陌生,不过您可知道xz是绝大数Linux默认就带的一个压缩工具. 之前xz使用一直很少,所以几乎没有什么提起. 我是在下载phpmyadmin的时候看到 ...

  6. Oracle存储过程记录异常

    --建立错误日志表 create table PUB_PROC_ERR_LOG ( LOG_ID NUMBER, MODULE_NAME ), PROC_NAME ), ERR_TIME DATE, ...

  7. 09-JAVA中的异常处理

    1. 程序执行结果: 也就是它根本就没抛出异常,更别提捕获异常了.那么,为什么会这样呢? 原来, 如上面程序展示,程序运行到k=i/j;的时候,就会直接终止,根本就不会运行到监视的程序,更不会运行到捕 ...

  8. hibernateTemplate中常用查询方法的使用(原文地址: http://dongruan00.iteye.com/blog/1772311)

    一.find(String queryString); 示例:this.getHibernateTemplate().find("from bean.User"); 返回所有Use ...

  9. 使用 Sandcastle 生成代码帮助文档

    使用 Sandcastle可以生成MSDN风格的帮助文档,生成的帮助文档既可以是chm文档,也可以是MS Help 2.x帮助文档. 1 下载并安装Sandcastle Sandcastle下载地址为 ...

  10. 四元数(Quaternions)简介

    经常在代码中看到Quaternions,也知道它是用来表达三维空间的旋转的,但一直没有更深的理解.这两天终于花点时间看了看维基百科的介绍,算是多了解了点.做个记录吧! 本质上而言,四元数是一个数学概念 ...