您的位置:首页 > 编程语言 > Java开发

局部内部类和匿名内部类访问final的局部变量---一个元素的数组

2017-10-24 14:57 260 查看
     在Java的内部类中,匿名内部类和局部内部类在访问局部变量时,局部变量只能是final的,在我的另一篇文章中分析了原因:为什么局部内部类和匿名内部类只能访问final的局部变量?

   虽然final保证了局部变量与在局部类内建立的拷贝保持一致,但有时final限制却显得不太方便。在学习《java核心卷术 卷1》这本书时,里面给出了一种改善这种限制的方案:

       例如:假设想更新在一个封闭作用域内的计数器。这里想要统计一下在排序过程中调用compareTo方法的次数:

public class Demo {
public static void main(String[] args) {
int counter = 0;
Date[] dates = new Date[100];
for (int i = 0; i < 100; i++) {
dates[i] = new Date() {
/*
* 下面相当于建立了Date类的一个匿名子类,并添加了新的compareTo方法
*/
public int compareTo(Date other) {
counter++;//Error:Cannot refer to a non-final variable counter inside an inner class defined in a different method
return super.compareTo(other);
}
};
}
Arrays.sort(dates);
System.out.println("次数:" + counter);
}
}

       由于清楚的知道counter需要进行更新,所以counter不能设置为final。由于Integer对象是不可变的,也不能用Integer去代替它。补救的方法是使用一个长度为1的数组:

public class Demo {
public static void main(String[] args) {
final int[] counter = new int[1];
Date[] dates = new Date[100];
for (int i = 0; i < 100; i++) {
dates[i] = new Date() {
public int compareTo(Date other) {
counter[0]++;
return super.compareTo(other);
}
};
}
Arrays.sort(dates);
System.out.println("次数:" + counter[0]);
}
}

      
数组变量虽然被定义为final的,但这仅仅表示不可以让这个数组变量引用另外一个数组,数组中的数据元素仍然可以被改变。
 

       至于编译器是怎么编译匿名内部类的,我们可以反编译生成的.class文件,如下:



      可以看到,匿名内部类确实是extends了Date类,并扩展了新的compareTo方法,也即相当于下面的形式:

public class Demo {
public static void main(String[] args) {
Date[] dates = new Date[100];
for (int i = 0; i < 100; i++) {
dates[i] = new myDate();
}
Arrays.sort(dates);
System.out.println(myDate.getCounter());
}

}

class myDate extends Date {

private static int counter = 0;

@Override
public int compareTo(Date anotherDate) {
counter++;
return super.compareTo(anotherDate);
}

public static int getCounter() {
return counter;
}
}

       此时就可以看到,由于只需要对compareTo方法进行小小的修改,并且不需要知道myDate类的存在,使用匿名内部类会更加的简洁,处理起来也会更加的方便。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐