1. 内部类里面使用外部类的局部变量时,其实就是内部类的对象在使用它,内部类对象生命周期中都可能调用它,而内部类试图访问外部方法中的局部变量时,外部方法的局部变量很可能已经不存在了,那么就得延续其生命,拷贝到内部类中,而拷贝会带来不一致性,从而需要使用final声明保证一致性。说白了,内部类会自动拷贝外部变量的引用,为了避免:1. 外部方法修改引用,而导致内部类得到的引用值不一致 2.内部类修改引用,而导致外部方法的参数值在修改前和修改后不一致。于是就用 final 来让该引用不可改变。

2. 内部类通常都含有回调,引用那个匿名内部类的函数执行完了就没了,所以内部类中引用外面的局部变量需要是final的,这样在回调的时候才能找到那个变量,而如果是外围类的成员变量就不需要是final的,因为内部类本身都会含有一个外围了的引用(外围类.this),所以回调的时候一定可以访问到。例如:

private Animator createAnimatorView(final View view, final int position) {
MyAnimator animator = new MyAnimator();
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationEnd(Animator arg0) {
Log.d(TAG, "position=" + position);
}
});
return animator;
}

内部类回调里访问position的时候createAnimatorView()早就执行完了,position如果不是final的,回调的时候肯定就无法拿到它的值了,因为局部变量在函数执行完了以后就被回收了。

3. 我们反编译看一下,首先定义接口和匿名内部类:

public interface MyInterface {
void doSomething();
} public class TryUsingAnonymousClass {
public void useMyInterface() {
final Integer number = 123;
System.out.println(number); MyInterface myInterface = new MyInterface() {
@Override
public void doSomething() {
System.out.println(number);
}
};
myInterface.doSomething(); System.out.println(number);
}
}

我们进行反编译,结果是:

class TryUsingAnonymousClass$1
implements MyInterface {
private final TryUsingAnonymousClass this$0;
private final Integer paramInteger; TryUsingAnonymousClass$1(TryUsingAnonymousClass this$0, Integer paramInteger) {
this.this$0 = this$0;
this.paramInteger = paramInteger;
} public void doSomething() {
System.out.println(this.paramInteger);
}
}

可以看到名为number的局部变量是作为构造方法的参数传入匿名内部类的。

如果Java允许匿名内部类访问非final的局部变量的话,那我们就可以在TryUsingAnonymousClass$1中修改paramInteger,但是这不会对number的值有影响,因为它们是不同的reference。

这就会造成数据不同步的问题。

所以,Java为了避免数据不同步的问题,做出了匿名内部类只可以访问final的局部变量的限制。

参考:http://cuipengfei.me/blog/2013/06/22/why-does-it-have-to-be-final/

匿名内部类为什么访问外部类局部变量必须是final的?的更多相关文章

  1. 内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例

    内部类访问外部类的变量必须是final吗? 如下: package com.java.concurrent; class A { int i = 3; public void shout() { cl ...

  2. 深入理解Java中为什么内部类可以访问外部类的成员

    内部类简介 虽然Java是一门相对比较简单的编程语言,但是对于初学者, 还是有很多东西感觉云里雾里, 理解的不是很清晰.内部类就是一个经常让初学者感到迷惑的特性. 即使现在我自认为Java学的不错了, ...

  3. Java基础-内部类-为什么成员内部类可以无条件访问外部类

    在此之前,我们已经讨论过了成员内部类可以无条件访问外部类的成员,那具体究竟是如何实现的呢?下面通过反编译字节码文件看看究竟.事实上,编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件,下面 ...

  4. “全栈2019”Java第八十二章:嵌套接口能否访问外部类中的成员?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. “全栈2019”Java第七十二章:静态内部类访问外部类成员

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. “全栈2019”Java第六十九章:内部类访问外部类成员详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  7. C++中内部类访问外部类的私有成员

    首先,如果不知道什么是内部类InnerClass的话,就没必要往下看了. 尝试在C++中模仿apple objective-c 的Grand Dispatch简化多线程编程时,使用了boost::fu ...

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

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

  9. 匿名内部类可以访问的变量---静态成员变量和final修饰的局部变量

    在学习多线程的时候用到了匿名内部类,匿名内部类可以访问static静态成员变量或者final修饰的局部变量. 匿名内部类在编译之后会生成class文件,比如Test内的第一个匿名内部类编译之后就是Te ...

随机推荐

  1. android gridview画分割线,如图:

    1.先上图: 2.具体实现代码: public class LineGridView extends GridView { public LineGridView(Context context) { ...

  2. PHP-数组函数

    今天在写一个给第三方同步数据的接口时遇到一个这种情况,我有一大坨数据,但是第三方只需要其中的几个而已,不及思索的就开始foreach $ret = array(); foreach ($needPar ...

  3. shell 删除某个目录下的重复文件

    #!/bin/bash ls -lS | awk 'BEGIN{ getline; getline; name1=$;size=$; } { name2=$; sizeTmp=$; ){ ; ; if ...

  4. Conherence Function

    来源: 部分来自wiki:https://en.wikipedia.org/wiki/Coherence_(signal_processing): 部分来自网络其它内容. The coherence  ...

  5. BZOJ 1014 【JSOI2008】 火星人prefix

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  6. 微软职位内部推荐-Software Development Engineer

    微软近期Open的职位: Job Title: Software Development Engineer Work Location: Suzhou, China The Office 365 Co ...

  7. JPA 教程

    Entities An entity is a lightweight persistence domain object. Typically an entity represents a tabl ...

  8. single-write-database-connection

    http://ithare.com/ultimate-db-heresy-single-db-connection-part-i-performance-part-ii-scalability-to- ...

  9. velocity模板引擎学习(1)

    velocity与freemaker.jstl并称为java web开发三大标签技术,而且velocity在codeplex上还有.net的移植版本NVelocity,(注:castle团队在gith ...

  10. Fragment生命周期