为什么匿名内部类只能访问final变量【转】
是变量的作用域的问题,因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为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变量【转】的更多相关文章
- Java 匿名内部类 只能访问final变量的原因
文章来源:http://blog.sina.com.cn/s/blog_4b6f8d150100qni2.html 1)从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方 ...
- 匿名内部类和局部内部类只能访问final变量的原因
以下是从各大网站找来的解释,我在这里摘抄一些从其他地方搬过来的大致思想,可能会比较乱, 详细解释 http://blog.csdn.net/salahg/article/details/7529091 ...
- 为什么匿名内部类和局部内部类只能访问final变量
因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或 ...
- 为什么局部内部类和匿名内部类只能访问 final 的局部变量?
首先,我们看一个局部内部类的例子: class OutClass { private int age = 12; public void outPrint(final int x) { class I ...
- 局部内部类为什么只能访问final局部变量,对于成员变量却可以随便访问?
局部内部类为什么只能访问final局部变量,对于成员变量却可以随便访问? public class OuterClass { private int memberField = 10; public ...
- Java学习笔记23---内部类之局部内部类只能访问final的局部变量
局部内部类是定义在方法体或代码块中的类,在笔记19中已有过简单介绍. 今天要讨论的是局部内部类为什么只能访问为常量的局部变量. 作者: 博客园--蝉蝉 请尊重作者劳动成果,转载请在标题注明“转载”字样 ...
- Java基础-内部类-为什么局部和匿名内部类只能访问局部final变量
先看下面这段代码: public class Test { public static void main(String[] args) { } public void test(final int ...
- 匿名内部类中使用的外部局部变量为什么只能是final变量
被匿名内部类引用的变量会被拷贝一份到内部类的环境中 但其后,在外部,该变量如果被修改,则内部外部不一致 Java为了避免数据不同步的问题,做出了匿名内部类只可以访问final的局部变量的限制. 究其原 ...
- 为什么匿名内部类只能访问其所在方法中的final类型的局部变量?
大部分时候,类被定义成一个独立的程序单元.在某些情况下,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类. class Outer { priv ...
随机推荐
- LinQ高级查询
1.模糊查询 con.Users.Where(a =>a.UserName.Contains(name)).ToList(); //包含name con.Users.Where(a =>a ...
- 利用开源程序(ImageMagick+tesseract-ocr)实现图像验证码识别
--------------------------------------------------低调的分割线-------------------------------------------- ...
- TTL、RS232、RS485、串口
Point: 1.串口.COM口是指的物理接口形式(硬件).而TTL.RS-232.RS-485是指的电平标准(电信号). 2.接设备的时候,一般只接GND RX TX.不会接Vcc或者+3.3v的电 ...
- (转载)python2+selenium自动化测试系列(一)
1.Selenium2+python自动化1-环境搭建 2.Selenium2+python自动化2-pip降级selenium3.0 3.Selenium2+python自动化3-解决pip使用异常 ...
- 利用SlidingPaneLayout实现侧滑
利用SlidingPaneLayout实验仿QQ侧滑效果 1.效果图 2.布局文件 <?xml version="1.0" encoding=" ...
- powerdesigner连接数据库 导出数据
powerdesigner连接数据库 导出数据 生成PDM文件 傻瓜试教程 也可下载文档:http://download.csdn.net/detail/shutingwang/6378665 ...
- ngRoute插件
angular中可以使用插件,例如ngRoute插件就是用与路由控制. 首先要在模块中引入即可: var m1 = angular.module('myApp',['ngRoute']); 然后我们进 ...
- ssh注解整合
ssh注解整合 导入java包 配置struts2环境 1. 创建struts.xml配置文件 <?xml version="1.0" encoding="UTF- ...
- 【如何快速的开发一个完整的iOS直播app】(原理篇)
原文转自:袁峥Seemygo 感谢分享.自我学习 目录 [如何快速的开发一个完整的iOS直播app](原理篇) [如何快速的开发一个完整的iOS直播app](播放篇) [如何快速的开发一个完整的 ...
- iOS10字体
iOS10字体随着手机系统的字体改变,当我们手机系统字体改变以后,我们的app的lable也会跟着一起变化: 同样的6sp,在iOS9上面运行字体显示是没问题的,当我的手机更新了iOS10以后,有的界 ...