以下是从各大网站找来的解释,我在这里摘抄一些从其他地方搬过来的大致思想,可能会比较乱,

详细解释

http://blog.csdn.net/salahg/article/details/7529091

3.1.原因解析

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

这是一个编译器设计的问题,如果你了解java的编译原理的话很容易理解。

首先,内部类被编译的时候会生成一个单独的内部类的.class文件,这个文件并与外部类并不是一个class文件。

因为编译的时候内部类和方法在同一级别上,所以方法中的变量或参数只有为final,内部类才可以引用。

当外部类传的参数被内部类调用时,从java程序的角度来看是直接的调用

例如

public void dosome(final String a,final int b){
class Dosome{public void dosome(){System.out.println(a+b)}};
Dosome some=new Dosome();
some.dosome();
}

从代码来看好像是那个内部类直接调用的a参数和b参数,但是实际上不是,在java编译器编译以后实际的操作代码是

class Outer$Dosome{
public Dosome(final String a,final int b){
this.Dosome$a=a;
this.Dosome$b=b;
}
public void dosome(){
System.out.println(this.Dosome$a+this.Dosome$b);
}
}
}

从以上代码看来,内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。

这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。 (简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变)

3.2.个人的理解

(我对上面这段话的大致理解是这样的:虽然内部类是在外部类里面,但是在编译之后这是两个不同的class文件,而内部类在使用外部类的成员变量之后,却被编译成了两个不同的class文件,所以内部类中使用的那个从外部类传过来的那个变量实际并不是外部类中的变量,只是外部类变量的一个拷贝,这样就导致了即使内部类中修改了该变量的值,也不会让外部类中的那个变量发生任何改变,这样就导致一个情况,在同一个Java程序里面,同样名字的一个变量却同时产生了两个不同的值!这是非常荒唐的一件事情,就相当于a等于1的同时又等于2,失去了参数的一致性,所以为了避免这种问题,所以限定内部类可以使用的参数必须为final类型 因为当变量是final时,如果是基本数据类型,由于其值不变,因而:其复制品与原始的量是一样。语义效果相同.(若如果不是final,就无法保证:复制品与原始变量保持一致了,因为在方法中改的是原始变量,而局部内部类中改的是复制品),所以为了保证内部类和外部类中这两个变量值的一致性,所以就把内部类可以使用的外部类的变量限定成final,让内部类无法再修改使用的参数的值,从而避免出现a等于1的同时又等于2这种情况,保证了参数值的一致性)

匿名内部类和局部内部类只能访问final变量的原因的更多相关文章

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

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

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

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

  3. 为什么匿名内部类只能访问final变量【转】

    是变量的作用域的问题,因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final.因为虽然匿名内部类在方法的内部,但实际编译的时候, ...

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

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

  5. java--局部类只能访问外包方法的final局部成员

    class B523{ // private int k = 10; public void go(int x, final int y){ // int a = x+y; final int b = ...

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

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

  7. Java知多少(37)静态内部类、匿名内部类、成员式内部类和局部内部类

    内部类可以是静态(static)的,可以使用 public.protected 和 private 访问控制符,而外部类只能使用 public,或者默认. 成员式内部类 在外部类内部直接定义(不在方法 ...

  8. 《Java基础知识》Java静态内部类、匿名内部类、成员式内部类和局部内部类

    内部类可以是静态(static)的,可以使用 public.protected 和 private 访问控制符,而外部类只能使用 public,或者默认. 成员式内部类 在外部类内部直接定义(不在方法 ...

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

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

随机推荐

  1. js 淡入淡出的tab选项卡

    代码如下 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...

  2. Flask 特殊装饰器

    请求进入函数之前 before_request # -*- coding: utf-8 -*-   from flask import Flask, session, redirect, reques ...

  3. ionic + cordova安装指南

    安装ionic --npm install -g ionic --cnpm install -g ionic --npm update -g ionic --cnpm update -g ionic ...

  4. ES6-promise对象的使用

    Promise 的含义(摘自阮一峰ES6ru) Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一 ...

  5. 【Beta阶段】第十一周Scrum会议

    [Beta阶段]第十一周Scrum会议 本次会议为第十一周第一次Scrum Meeting,会议对上周工作进行了总结,并对工作成果予以了肯定. 会议时间为2019.11.28.会议地点为中国海洋大学北 ...

  6. CSS新特性之3D转换

    1. 三维坐标系 x轴:水平向右(右边是正,左边是负) y轴:垂直向下(向下是正,向上是负) z轴:垂直屏幕(向外是正,向里是负) 2. 3D转换 3D转换中最常用的是3D位移和3D旋转.主要知识点如 ...

  7. 开发一个这样的 APP 要多长时间?

    作者:蒋国刚 www.cnblogs.com/guogangj/p/4676836.html 这是一个“如有雷同,纯属巧合”的故事,外加一些废话,大家请勿对号入座.开始了…… 我有些尴尬地拿着水杯,正 ...

  8. Spring 中的观察者模式

    一.Spring 中观察者模式的四个角色 1. 事件(ApplicationEvent) ApplicationEvent 是所有事件对象的父类.ApplicationEvent 继承自 jdk 的 ...

  9. 了解Github

    一.什么是Github Github是全球最大的社交编程及代码托管网站(https://github.com/). Github可以托管各种git库,并提供一个web界面(用户名.github.io/ ...

  10. 5面终于拿到了字节跳动offer! 鬼知道我经历了啥...

    坐标北京,某211本科毕业生,之前学校活动有去过字节跳动公司总部参观,所以一直以来就蛮想进入字节工作的,被字节的企业文化和工作氛围所影响.字节作为发展速度最快的互联网公司,旗下的很多产品的用户都比肩B ...