内部类学习笔记

内部类(Inner Class)

可以将一个类的定义放在另一个类的定义内部,这就是内部类。

内部类特点

  • 可用public、protected、private和默认(package-private)关键字修饰,作用域跟普通类的作用于相同。
// A称之为外围类
public class A {

    // 用public关键字修饰可以被所有类访问
    public class AA {}
    
    // 用protected关键字修饰可以被自身、外部类、子类访问
    protected class AB {}
    
    // 只能被外部类和自身访问
    private class AC {}
    
    // 只能被自身、同包的类访问到
    class AD {}
    
    // 只有同外部类的内部类才能继承改外部类的其他内部类
    class AE extends AB {}
    
    public static void main(String... args) {
        // 外围类实例化后的对象才能实例化内部类
        A a = new A();
        A.AE ae = a.new AE();
    }
}
  • 内部类能访问其外围对象的所有成员,而不需要任何特殊条件
public class A {
    private final int i = 1;
    public class B {
        public int getI() {
            return i;
        }
    }
}
  • 静态内部类(嵌套类)不需要对外部类对象的引用。
public class A {
    public static B {
        
    }
    public static void main(String... args) {
        // 嵌套类不需要对外部类对象的引用
        A.B b = new A.B();
    }

}
  • 内部类与向上转型,例子如下
public class A {

    // 通过扩展接口
    private class AA implements FInterface {
        @Override
        public void print() {
            System.out.println("hehe");
        }
    }
    // 向上转型
    public FInterface getF() {
        return new AA();
    }
}

public class B {
    public static void main(Stirng... args) {
        A a = new A();
        // AA是内部私有类,除了AA本身和外围类,其他类均无法访问
        // 这时向上转型为接口就能调用AA的方法
        FInterface f = a.getF();
        // 控制台将会输出"hehe"
        f.print();
        
        /*
            事实上,f也不能向下转型,通过这样的方式
            隐藏实现的细节。
        */
    }
}

上面举的例子都是内部类在外围类中的,实际上内部类还包括局部内部类、匿名内部类、嵌套类。

局部内部类

public class A {

    private static int i = 1;
    public void methodA() {
        // 局部内部类,不能添加作用域
        // 因为局部内部类只能在该局部方法中存在
        // 换句话说,除了methodA方法,其他地方不存在该内部类
        class AAA {
            private int i = A.i;
        }
        AAA a = new AAA();
    }
}

匿名内部类

public class A {
    private int i = 1;
    public void methodA(final int i) {
        A a = new A() {
            // 在匿名内部类中,想要访问外部定义的对象
            // 需要添加final使之变成常量
            int l = i;
        };
    }
}

嵌套类

如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为static。这通常称为嵌套类。

特点
  • 要创建嵌套类的对象,不需要其外围类的对象
  • 不能从嵌套类的对象中访问非静态的外围类对象
  • 普通内部类的字段和方法只能放在类的外部层次上,所以普通的内部类不能有static数据和字段,但是嵌套类可以包含这些东西
public class A { 

    private int a = 1;
    private static class AA {
        // 嵌套类可以定义静态属性
        public static int i = 1;
        
        // 这样做编译器会报错
        // 不能从嵌套类的对象中访问非静态的外围类对象
        public static int i = a;
    }
    
    public static void main(String... args) {
    
        // 创建嵌套类不需要其外围类的对象
        A.AA aa = new A.AA();
        System.out.println(aa.i);
    }
}

接口内部的类

嵌套类可以作为接口的一个部分。在接口中的任何类都自动为public和static的,只是将嵌套类置于接口的命名空间中,这并不违反接口的规则。如果你想要创建某些公共代码,使得他们可以被某个接口的所有不同实现所共有,那么在接口中使用嵌套类会显得方便。(有点像抽象类)

interface AInterface {
    void print();
    // 自动为public、static
    class A implements AInterface {
        @Override
        public void print() {
            System.out.println("heheda");
        }
    }
}

为什么需要内部类

每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的实现),对于内部类都没有影响。

  • 如果没有内部类提供的可以继承多个具体或抽象的类的实现,一些设计和编程问题将很难解决。
  • 还有Json一些复杂数据转换成java对象也将变得不简单??

闭包(closure)

闭包是一个可调用的对象,它记录了来自于创建它的作用域的信息。 因为内部类能够访问外围类的任何属性方法,所以用内部类来实现闭包的功能是非常棒的。

内部类标识符

由于每个类都会产生一个.class文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个“meta-lcass”,叫做Class对象),内部类也必须创建一个.class文件已包含他们的Class对象信息。 这些类文件的命名有规范:外围类的名字加上"$",再加上内部类的名字,如果是匿名的,编译器会简单产生一个数字作为标识符。

转载于:https://my.oschina.net/StupidZhe/blog/1557600

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值