理解Java内部类
2016-07-06 15:41
225 查看
内部类分为成员内部类、局部内部类、静态内部类和匿名内部类。
成员内部类就是像类成员变量一样定义一个class, 作用域是外部类内; 局部内部类定义在函数里, 作用域就在函数内, 类似于局部变量; 静态内部类就是添加static关键字, 静态类内部不能访问外部类的非静态变量了。
这里有个知识点, 内部类里为什么能够得到外部类成员变量的值? 因为内部类持有外部类的引用, 具体参见http://www.tuicool.com/articles/Nj2qUz7
我觉得比较难理解的是匿名内部类, 它的表现方式是new ...{}, 典型场景就是按钮点击回调或其它各种回调。 我觉得比较难理解的是为什么叫匿名。 其实看看编译生成的.class文件就明白了, 它是按照$1,$2,$3等等方式命名的。
如上图所示BaseActivity$MyOnNetChangeListener.class中MyOnNetChangedListener.class就是成员内部类。 没真正名字用1/2/3等等命名的就是匿名内部类了, 如DifferentMenuActivity$1.class。
外部类可以访问非静态内部类的私有成员和方法, 内部类也可以访问外部类的私有成员和方法。
为什么内部类可以访问外部类的私有成员? 因为内部类持有外部类的引用! 执行javap -p -v TestInner$Inner.class反编译出字节码, 可以看出编译器自动添加了一个构造函数,并传入外部类的引用。
为什么外部类可以访问内部类的私有成员? 因为编译器会自动生成access$100方法!
反编译.class文件,可以看到getValue方法里调用access$100方法。
使用反射也可以看到TestInner类方法数是3, 多个一个access$000方法, 这是因为函数体访问了内部类的私有变量。
匿名内部类访问外部变量时必须添加final关键字, 以下面代码为例。 Runnable内部类中total参数实际是外部类total的拷贝。 如果外部类修改该外部类参数, 内部类中对应的拷贝不会随之改变, 从而可能出现数据不一致问题。 为了避免这个问题, Java语法规定要用final关键字声明为常量。
final int total = 100;
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(total); //实际是外部变量total的一个拷贝
}
}).start();
成员内部类就是像类成员变量一样定义一个class, 作用域是外部类内; 局部内部类定义在函数里, 作用域就在函数内, 类似于局部变量; 静态内部类就是添加static关键字, 静态类内部不能访问外部类的非静态变量了。
这里有个知识点, 内部类里为什么能够得到外部类成员变量的值? 因为内部类持有外部类的引用, 具体参见http://www.tuicool.com/articles/Nj2qUz7
我觉得比较难理解的是匿名内部类, 它的表现方式是new ...{}, 典型场景就是按钮点击回调或其它各种回调。 我觉得比较难理解的是为什么叫匿名。 其实看看编译生成的.class文件就明白了, 它是按照$1,$2,$3等等方式命名的。
如上图所示BaseActivity$MyOnNetChangeListener.class中MyOnNetChangedListener.class就是成员内部类。 没真正名字用1/2/3等等命名的就是匿名内部类了, 如DifferentMenuActivity$1.class。
外部类可以访问非静态内部类的私有成员和方法, 内部类也可以访问外部类的私有成员和方法。
public class TestInner { private String name; Inner instance; TestInner() { instance = new Inner(); } class Inner { public Inner() { value = 0; } private int value; public void showLog() { System.out.print(name); //访问外部类的私有变量 } } public int getValue() { return instance.value; //访问内部类的私有变量 } public void setValue(int value) { instance.value = value; } }
为什么内部类可以访问外部类的私有成员? 因为内部类持有外部类的引用! 执行javap -p -v TestInner$Inner.class反编译出字节码, 可以看出编译器自动添加了一个构造函数,并传入外部类的引用。
为什么外部类可以访问内部类的私有成员? 因为编译器会自动生成access$100方法!
反编译.class文件,可以看到getValue方法里调用access$100方法。
使用反射也可以看到TestInner类方法数是3, 多个一个access$000方法, 这是因为函数体访问了内部类的私有变量。
匿名内部类访问外部变量时必须添加final关键字, 以下面代码为例。 Runnable内部类中total参数实际是外部类total的拷贝。 如果外部类修改该外部类参数, 内部类中对应的拷贝不会随之改变, 从而可能出现数据不一致问题。 为了避免这个问题, Java语法规定要用final关键字声明为常量。
final int total = 100;
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(total); //实际是外部变量total的一个拷贝
}
}).start();
相关文章推荐
- java匿名内部类实例简析
- java中匿名内部类解读分析
- java中的匿名内部类详细总结
- 简单谈谈java中匿名内部类构造函数
- java中的匿名内部类总结
- java中的匿名内部类总结
- 回看基础--Java内部类详解
- 【黑马程序员】Java学习笔记之继承(二)(面向对象)
- 匿名内部类
- 黑马程序员—内部类与匿名内部类 异常
- 内部类(匿名内部类)
- 匿名内部类的传参
- 初次对内部类的理解
- 回看基础--Java内部类详解
- 黑马程序员—java面向对象总结(4)—内部类、异常
- 关于Java中的匿名内部类
- 黑马程序员_Java内部类
- Java匿名内部类总结
- 嵌套类,内部类,匿名内部类的定义和使用方法
- 成员内部类、局部内部类、静态内部类和匿名内部类区别