java 的匿名内部类可以访问所在类的私有属性以及方法的final 声明的值,如下代码:
public interface NoName{
public void say(); //这是一个接口方法
}
Public Class Test{
private Stri+ng text1;
public Test(){
final int testNum=3;
new NoName(){
public void say(){
System.out.println(text1); //在这里可以访问text1值
System.out.println(testNum); //在这里可以访问testnum的值
//testNum=4;error我们不能改变final的值
}
};
}
public void setText1(String text){
this.text1=text;
}
public String getText1(){
return this.text1;
}
我们不仅思考,为什么我们在访问方法的局部变量的时候,要声明成为final的值呢?
我们现在声明一个Person的类
public class Person{
private String name;
public void setName(String name){
this.name=name;
}
public String getName(){
return this.name;
}
}
然后,我们在匿名类里面重载say方法
final Person p1=new Person;
new NoName(){
public say(){
p1.setName("corey");
p1=new Person();//error
}
};
在这里我们能够改变p1的值;
这是因为匿名类会将final属性作为一个模板拷贝到自己的实例内存区中作为一个属性字段
如:p1----> |--------|
| name |
| |
|--------|
这个时候p1的指向是固定不变的,我们虽然能改变里面的name值,但是p1=new Person();的时候会发生
p1----| |--------|
| | name |
| | |
| |--------|
|--> |--------|
| name |
| |
|--------|
这个时候违背了final原则,设计的最初的为了给使用匿名类的人造成歧义 因为我们说了匿名类中的类在访问方法的变量的时候,是将这个final变量拷贝
p1----> |--------| <-----------p'1
| name |
| |
|--------|
这个时候,我们如果不用final的话 我们可能会作出这样的操作p1=new Person();,我们会把p‘1的内存区当作p1处理(事实上我们认为我们访问和改变的是p1变量)
p1-------->|--------|
| name |
p'1---| | |
| |--------|
|--> |--------|
| name |
| |
|--------|
但是事实上p1变量是没有作出修改的,我们利用内部类处理方法中的变量,本身就是为了改变他,而现在我们
在改变另外一个内存区里面的数据,而目标区域没有得到改变!
这也是为什么sun在设计的时候要规定必须声明为final