当一个事物 A 的内部,还有一个部分需要一个完整的结构 B 进行描述,而这个内部的完整的结构 B 又只为外部事物 A 提供服务,不在其他地方单独使用,那么整个内部的完整结构 B 最好使用内部类。颇有细胞,组织,器官,系统,个体,种群,群落,生态系统,生物圈的感觉了。一层又一层的封装。遵循高内聚、低耦合的面向对象开发原则。该隐藏的隐藏,该暴露的暴露。
内部类,在类里边。那是和属性们待在一起还是和方法们待在一起?
所以有成员内部类和局部内部类的区分。
成员内部类
因为作为类的一部分存在,所以也会有和类绑定的情况,此时static也可以修饰内部类(注:仅限内部类,外部类不可以哦)
所以划分为静态成员内部类和非静态成员内部类。
(1)作为属性,作为类中的成员:可以声明为 private 或 protected(毕竟此时只算一个属性,有private可以隐藏一部分信息),可以调用外部类的结构。(注意:在静态内部类中不能使用外部类的非静态成员)
(2)作为类的角色:可以在内部定义属性、方法、构造器、代码块、内部类等结构;可以继承自己想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关;可以声明为 abstract 类 ,可以被其它的内部类继承;可以声明为 final 表示不能被继承;编译以后生成OuterClass$InnerClass.class 字节码文件(也适用于局部内部类)。从这一点来说,内部类使得类可以继承多个具体类或抽象类。
外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
• 成员内部类可以直接使用外部类的所有成员,包括私有的数据
• 当想要在外部类的静态成员部分使用内部类时,可以考虑声明内部类为静态的
• 在内部类中调用外部类的结构时,不重名可以直接调,重名之后就近原则,name -- this.name -- person.this.name
静态成员内部类
静态内部类不能再使用外层类的非 static 的成员变量;
被 static 修饰的内部类可以直接作为一个普通类来使用,不需要实例化一个外部类。
实例化静态内部类:
外部类名.静态内部类名 变量 = 外部类名.静态内部类名();
变量.非静态方法();
那么静态内部类可不可以定义非静态方法呢?当然可以,只是变出非静态的东西后,必须创建对象才能调用(普通方法是属于对象的)。(因为在调的时候没有对象不知道调的到底是什么,这也是静态和非静态最大的区别:一个随类加载,一个没有。在不确定时,没法一起合作。)
非静态成员内部类
非静态内部类可以访问外部类的所有成员(方法、属性);
类似的,不被 static 修饰的内部类则需要实例化一个外部类。
实例化非静态内部类:
外部类名 变量 1 = new 外部类();
外部类名.非静态内部类名 变量 2 = 变量 1.new 非静态内部类名();
变量 2.非静态方法();
参考链接:https://blog.csdn.net/zuo_er_lyf/article/details/103488246
局部内部类
局部内部类,就是放在类的方法、构造器、代码块里的一个类,这个类是为这些方法等服务的,作用域小,是不是一定要有名字呢?
所以有匿名局部内部类和非匿名局部内部类的区分。
开发中一般见到的是调用的方法需要返回接口的实例,需要提供实现接口的类,返回实现接口类的对象。
一般常看见的代码有提供接口的实现类的对象、接口的实现类的匿名对象、接口的匿名实现类的对象和接口的匿名实现类的匿名对象。
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名、$符号、编号(有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类)。
• 和成员内部类不同的是,它前面不能有权限修饰符等
• 局部内部类和局部变量一样,有作用域
• 局部内部类中是否能访问外部类的非静态的成员,取决于所在的方法