内部类

类都对应一个独立的java源文件 ,一个类放在另外一个类里面,成为内部类。内部类和外部类关系密切,和其它类关系不大,定义在类内部,可以实现对外部的完全隐藏,有更好的封装性,代码更简洁。
内部类只是java编译器的概念,对于虚拟机而言,他是不知道的,每个内部类最后都会编译成一个独立的字节码文件

在Java中,根据定义的位置和方式不同,主要有四种内部类:

静态内部类
成员内部类
方法内部类
匿名内部类

1.静态内部类:带有static关键字,可以访问外部内的静态变量和方法,无法访问实例变量和方法,在语法上与一个独立的类差别不大,可以有静态变量、静态方法、成员方法、成员变量、构造方法等。

public class Outer {
    private static int shared = 100;
    
    public static class StaticInner {
        public void innerMethod(){
            System.out.println("inner " + shared);
        }
    }
    
    public void test(){
        StaticInner si = new StaticInner();
        si.innerMethod();
    }
}

编译后:

    `public class Outer {
    private static int shared = 100;
    public void test(){
        Outer$StaticInner si = new Outer$StaticInner();
        si.innerMethod();
    }
    
   static int access$0(){
        return shared;
    }
}
public class Outer$StaticInner {
    public void innerMethod() {
        System.out.println("inner " + Outer.access$0());
    }
}`

可以看到,编译后,内部类之所以能访问到外部类的私有变量,是因为自动为外部内生成了一个非私有访问方法,返回私有变量。

成员内部类
1.成员内部类没有static修饰符。
2.成员内部类可以直接访问外部类的实例变量和方法,可用过 类名.this.方法名()去访问,这一般用于有重名方法的情况下。
3.成员内部类对象总是与一个外部类对象相连的。

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.innerMethod();

4.成员内部类中不可以定义静态变量和方法 (final变量例外,它等同于常量)

//内部类
public class Outer {
    private int a = 100;

    private void action() {
        System.out.println("action");
    }

    public void test() {
        Outer$Inner inner = new Outer$Inner(this);
        inner.innerMethod();
    }

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

    static void access$1(Outer outer) {
        outer.action();
    }
}
//内部类
public class Outer$Inner {

    final Outer outer;
    
    public Outer$Inner(Outer outer){
        ths.outer = outer;
    }
    
    public void innerMethod() {
        System.out.println("outer a "
                + Outer.access$0(outer));
        Outer.access$1(outer);
    }
}

通过编译后的文件可以看出,是把外部内作为实例变量放在内部类的属性中,基本上实现方法和静态内部类是差不多的。
Outer$Inner类有个实例变量outer指向外部类的对象,它在构造方法中被初始化

方法内部类
定义在方法体里面

public class Outer {
    private int a = 100;
    
    public void test(final int param){
        final String str = "hello";
        class Inner {
            public void innerMethod(){
                System.out.println("outer a " +a);
                System.out.println("param " +param);
                System.out.println("local var " +str);
            }
        }
        Inner inner = new Inner();
        inner.innerMethod();
    }
}

如果方法是实例方法,则 内部类可以访问外部类的实例变量和方法,如果是静态,则只能访问静态变量和方法。
方法内部类可以直接方法方法的参数,和方法中的局部变量,不过这些变量和参数必须被final声明。

public class OuterInner {
    Outer outer;
    int param;
    
    OuterInner(Outer outer, int param){
        this.outer = outer;
        this.param = param;
    }
    
    public void innerMethod() {
        System.out.println("outer a "
                + Outer.access$0(this.outer));
        System.out.println("param " + param);
        System.out.println("local var " + "hello");
    }
}

这就是为什么方法内部类可以访问方法的局部变量和参数,编译后,**参数就直接变成了内部类的属性,所以内部类实际上就变成了直接访问的是自己的实例变量。**只是这些值和外部的值是一样的,为这些值赋值,并不会改变外部的值,为了避免混淆。所以干脆强制规定为final修饰。

匿名内部类`
匿名内部类没有名字,
只有被只用一次,用来创建一个对象。他没有名字,没有构造方法。
自己无法接受参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值