成员内部类,局部内部类,匿名内部类
非 静态成员内部类
public class InnerClassDemo {
public static void main(String[] args) {
InnerClassDemo innerClassDemo = new InnerClassDemo();
}
class TestDemo {
}
}
非 静态成员内部类反编译class
public class InnerClassDemo{
class TestDemo{
final InnerClassDemo this$0;
TestDemo(){
this.this$0 = InnerClassDemo.this;
super();
}
}
public InnerClassDemo(){
}
public static void main(String args[]){
InnerClassDemo innerClassDemo = new InnerClassDemo();
}
}
静态内部类
public class InnerClassDemo {
public static void main(String[] args) {
InnerClassDemo innerClassDemo = new InnerClassDemo();
}
static class TestDemo {
}
}
静态内部类反编译class
public class InnerClassDemo{
static class TestDemo{
TestDemo(){
}
}
public InnerClassDemo(){
}
public static void main(String args[]){
InnerClassDemo innerClassDemo = new InnerClassDemo();
}
}
1.对比看的很清楚,编译器自动帮我们添加了无参的构造方法
2.非静态的成员内部类持有了外部类的引用
我们知道,静态方法是不能用this关键字的,this表示的是当前对象,
其实可以这么理解,静态的是类级别的,所以不能用this
内部类加static有什么区别,有什么好处?
静态内部类不依赖外部类,普通内部类与外部类之间是相互依赖的关系,
内部类实例不能脱离外部类实例,也就是说它们会同生同死,一起声明,
一起被垃圾回收器回收。
而静态内部类是可以独立存在的,即使外部类消亡了,静态内部类还是可以存在的。
普通内部类不能声明static的方法和变量 普通内部类不能声明static的方法和变量,
注意这里说的是变量,常量(也就是final static修饰的属性)还是可以的,而静态内部类形似外部类,
没有任何限制。
局部内部类,局部内部类不允许静态修饰
public class InnerClassDemo {
int i;
public static void main(String[] args) {
InnerClassDemo innerClassDemo = new InnerClassDemo();
innerClassDemo.show();
}
public void show() {
class TestDemo {
public void showInner() {
System.out.println(i);
}
}
TestDemo testDemo = new TestDemo();
testDemo.showInner();
}
}
局部内部类反编译
public class InnerClassDemo{
int i;
public InnerClassDemo(){
}
public static void main(String args[]){
InnerClassDemo innerClassDemo = new InnerClassDemo();
innerClassDemo.show();
}
public void show(){
class 1TestDemo{
final InnerClassDemo this$0;
public void showInner(){
System.out.println(i);
}
1TestDemo(){
this.this$0 = InnerClassDemo.this;
super();
}
}
1TestDemo testDemo = new 1TestDemo();
testDemo.showInner();
}
}
匿名内部类
public class InnerClassDemo {
public static void main(String[] args) {
InnerClassDemo innerClassDemo = new InnerClassDemo();
innerClassDemo.show();
}
public void show() {
final int i = 10;
new TestDemo1() {
@Override
public void showInner() {
System.out.println(i);
}
}.showInner();
}
}
abstract class TestDemo1 {
public abstract void showInner();
}
匿名内部类反编译
public class InnerClassDemo{
abstract class TestDemo{
final IntegerTest this$0;
public abstract void showInner();
TestDemo(){
this.this$0 = IntegerTest.this;
super();
}
}
public InnerClassDemo(){
}
public static void main(String args[]){
InnerClassDemo innerClassDemo = new InnerClassDemo();
innerClassDemo.show();
}
public void show(){
final int i = 10;
(new TestDemo() {
final IntegerTest this$0;
public void showInner(){
System.out.println(10);
}
{
this.this$0 = IntegerTest.this;
super();
}
}).showInner();
}
}
局部内部类访问成员变量不需要加final修饰,为啥访问局部变量需要加final修饰?
可以从生命周期的角度来解释
因为局部变量的生命周期是随着方法的调用是消失,而局部内部类可以理解为对象
当show方法调用完毕后,变量i的生命周期就结束了,而匿名对象的生命周期可能还未结束
那么在showInner()方法中访问变量i就变成了不可能了,但是要达到效果 应该怎么做,
Java采用了复制的手段来解决这个问题
如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。
如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值
但是这样会引来另外一个问题,如果在showInner()方法中改变i的值,会导致什么问题?
会出现数据不一致,这样就达不到以前的目的了,所以为了解决这个问题,Java编译器必须限定变量i为final变量,不允许对变量i进行改变(对于引用类型的变量,是不允许指向新的对象)