内部类

一、内部类的基本概念

二、内部类的实现原理

1. 普通内部类

先来建立一个简单的普通内部类

package inner.local;

import inner.InnerInterface;

public class Outer {

    private int out_int = 3;

    private void out_me () {}

    class Inner implements InnerInterface{

        private int in_int = 4;

        @Override
        public void getField () {
            int in_int = out_int;
        }

        @Override
        public void getMedthod() {
            out_me();
        }
    }
}

将Outer.java编译后,会发现在同一包下生产了两个class文件,一个外部类文件Outer.class和一个内部类文件Outer$Inner.class
这里写图片描述
将他们分别反编译后的结果如下

public class Outer {
    private int out_int = 3;

    private void out_me() {
    }

    static int access$0(Outer outer) {
        return outer.out_int;
    }

    static void access$1(Outer outer) {
        outer.out_me();
    }
}
class Outer$Inner implements InnerInterface {
    private int in_int = 4;
    //指向外部类的引用
    final Outer this$0;
    Outer$Inner(Outer paramOuter) {
        this$0 = paramOuter;
    }

    public void getField() {
        int in_int = Outer.access$0(this.this$0);
    }

    public void getMedthod() {
        Outer.access$1(this.this$0);
    }
}

结论:

  • 普通内部类编译后会生成一个内部类文件(Outer$Inner.class);
  • 普通内部类中含有一个指向外部类的引用(this$0);
  • 普通内部类中需要访问外部类变量和方法时,会在外部类中生成相应的静态方法(access0access1),通过指向外部类的引用(this0)access0和access$1)实现对外部类变量和方法的访问。
2.静态内部类

同理,写一个静态内部类实例

package inner.nest;

import inner.InnerInterface;
/**
 * 静态内部类中可以嵌套静态类和其他内部类,可以包含静态成员和方法
 */
public class Outer {

    //只能访问static变量
    private static int out_int = 3;

    //只能访问static方法
    private static void out_me () {}

    public static class Inner implements InnerInterface{
        @Override
        public void getField() {
            int in_int = out_int;
        }

        @Override
        public void getMedthod() {
            out_me();
        }
    }
}

同理,编译后内部类也生成class文件
这里写图片描述
反编译后的结果如下:

public class Outer{
    private static int out_int = 3;

    private static void out_me() {};
    //内部类可以访问的权限,因此不会生产额外的static方法
    static void out_me2() {};

    //为什么不直接调用静态属性、静态方法?
    //为了增加private修饰的权限
    static int access$0(Outer outer) {
        return outer.out_int;
    }

    static void access$1(Outer outer) {
        outer.out_me();
    }
}
package inner.nest;

import inner.InnerInterface;

public class Outer$Inner implements InnerInterface {
    public void getField() {
        int in_int = Outer.access$0();
    }

    public void getMedthod() {
        Outer.access$1();
        Outer.out_me2();
    }
}

结论:

  • 静态内部类中没有包含外部类的引用
  • 静态内部类中访问外部类变量和方法时,如果没有访问权限(out_int和out_me())则生成静态方法,如果拥有权限(out_me2())则不会生产额外方法
  • 静态内部类只能访问外部类的静态属性
3.方法内部类和匿名内部类
略。
4.内部类访问的局部变量为什么不可变(必须final修饰)?
  通过反编译文件,发现在Inner类中创建了一个局部变量的备份(因为方法的栈桢出栈后外部类的局部变量可能被回收)。将局部变量强制规定为final型,可以保持外部类中局部变量与内部类中的变量备份一致(如果没有final修饰,局部变量在外部类中修改,内部类中无法同时更改)。
  可以通过添加额外构造器,将局部变量传入构造器来回避这种语法。
class inner.anonymous.Outer$1 implements inner.InnerInterface {
  final inner.anonymous.Outer this$0;
  //局部变量备份
  private final inner.anonymous.Instance val$out_instance;
  inner.anonymous.Outer$1(inner.anonymous.Outer, inner.anonymous.Instance);
  public void getField();
  public void getMedthod();
}

三、内部类的应该场景

-实现回调(内部类拥有更好的封装特性)
- 实现多继承
- 更好的封装(可以用private ,protected修饰)
- 内部类有更好的灵活性,可以访问外部类的所有成员和方法

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值