* 引例
* 我们现在做一个应用程序,需要描述一台电脑中的CPU,对于电脑而言,该怎么去描述这个CPU呢?
*
* 分析:
* 我们可以创建两个类,一个描述Computer,一个描述CPU。
* 但这样明显是有问题的:
* 1.CPU是电脑中最重要的组件,但它脱离电脑存在就是一粒沙子。
* 这意味着CPU对象,应仅存在于Computer内部。
* 这个按照以往的知识语法是做不到的.
*
* 2.CPU可以控制计算机的一切硬件资源。
* 这意味CPU对象能够操控,Computer类中的所有成员,无论私有。
* 需求: 一个类的对象要能够无条件访问另外一个类的所有成员,无论私有
* 这个按照以往的知识语法也是做不到的.
*
* 定义普通类CPU是不能完成需求的,因为:
* 1.普通类没有私有概念,不可能控制仅能在Computer内部创建对象。
* 2.普通类不可能直接访问,其它类的私有成员。
* 显然CPU类不应该是一个普通类,不应该是一个独立的类
* ---> 不再将CPU类定义为一个独立的类
* 而是将它放入Computer类的类体中,可以近似的看成是一个Computer类的成员
* ---> CPU类近似看成Computer类的成员,于是:
*
* 1.在其它类内部的类,就有了私有概念,就有了四种访问权限。
* 只需要在内部私有化一个类,那么在外界就无法创建它的对象了。
* 2.既然已经成为了成员,成为了"自己人",那么就不再受限于权限控制了
* 内部类就可以访问包裹它的类的所有成员,包括私有。
*
* 上述两条,其实就是(成员)内部类的主要特点。也说明了使用内部类的主要场景:
* 1.内部类是一种比类更加极致的封装思想体现
* 内部类的成员不仅被类自身保护,还被包裹着它的类保护。
*
* 2.内部类和包裹它的类互相成为了"好兄弟"
* 互相访问成员都不受访问权限限制。
*
* 当你有以上使用场景时,就可以考虑使用内部类了。
* 学习内部类之前,声明:
* 内部类更多是一个为了精巧的设计而诞生的语法,不学习它,Java很多代码都看不懂
* 比如典型的集合体系
* 但是我们不是天生就会写精巧设计的,需要时间积淀
*
* 学习的要求:
* 学习内部类,不要求会使用,不要求会去做设计
* 只要求看懂语法,会用语法就可以了
*
* 为了上课方便,我们需要统一口径,在内部类课程当中,我们统一规定:
* 像CPU这种,定义在别的类的内部的类,我们称之为内部类。(inner)
* 像Computer这种,包裹内部类的,我们称之为外围类。(enclosed)
* Demo这种类我们称之为外部类。(outside)
*
* 成员内部类
* 成员内部类是最普通的内部类
* 它直接定义在另一个类的成员位置,可以近似看成该类的一个成员。
*
* 语法:
*
* [访问权限修饰符] class EnclosedClazz{
*
* [访问权限修饰符] class InnerClazz{
* }
* }
*
* 成员内部类的自身特点
* 主要从以下几个角度分析:
* 1.访问权限修饰符
* 四种访问级别皆可
* 而单独定义的class只有两种访问级别
* 既然使用内部类,普通都是为了封装,隐藏,保护类
* 所以内部类的访问权限,往往都是私有的.
*
* 2.成员特点
* 它仍然是一个类,虽然它是内部类
* 和普通类的成员相比,成员内部类当中是没有静态声明的:
* a.没有静态成员变量
* b.没有静态成员方法
* c.没有静态代码块
* 注意:
* 允许定义全局常量,但是不允许触发类加载的全局常量
* 也就是说只能定义字面值常量赋值的全局常量
*
* 除此之外,和普通类一样
* 有构造器,有构造代码块
*
* 3.继承和实现
* 既然它是一个类,虽然它是内部类
* 但是照样继承,照样实现
* 在开发中,成员内部类的继承和实现可以根据具体情况,具体对待
*
* 成员内部类怎么用?
* 类是创建对象的模板,定义成员内部类,最终还是需要创建对象的,还是需要new对象的
*
* 成员内部类最重要的特点/成员内部类和外围类的关系:
* 成员内部类可以看成外围类的一个成员。
* 要想得到成员内部类对象,必须先创建外围类对象。
* 这是因为: 成员内部类对象的成员变量列表中,会持有外围类对象的引用!!!
* 成员内部类和外围类之间是强依赖关系,成员内部类依赖于外围类,反过来不成立.
*
* 除以上关系外,还要铭记(这不是成员内部类独有的特点):
* 内部类和外围类之间是"好兄弟",它们之间的访问不受权限限制.
*
* 明确以上两点,现在来学习一下成员内部类的访问特点
* 主要从以下四个角度研究:
* 1.成员内部类内部访问外围类成员(重要)
* 访问的位置: 成员内部类的成员方法中(没有静态方法)
* 成员内部类的成员方法中存在几个对象?
* 首先肯定存在this指向当前对象,所以必然有自身类对象
* 除此之外还有外围类对象
* 有两个对象
* 既然有两个对象,那么访问外围类成员如何访问呢?
* 直接访问,而且访问不受权限限制.
*
* 极端情况下,会出现外围类,成员内部类同名成员变量,那怎么办呢?
* 语法:
* 在成员内部类的成员方法中
* this指向当前自身对象
* 外围类类名.this指向外围类对象
*
*
* 2.外围类访问成员内部类成员成员(重要)
* 访问的位置:
* 外围类是一个普通类
* 它有两种访问位置:
* 成员方法以及静态方法
*
* 这两个访问位置是有区别的
* 1.外围类的成员方法中访问成员内部类成员
* 这里存在什么对象?
* 只有this指向当前自身对象
* 外围类对象并不依赖于成员内部类
* 所以这里不存在成员内部类对象
* 所以想要访问它的成员,必须创建它的对象
* 如何创建呢?
* 要想得到成员内部类对象,必须先创建外围类对象。
* 在外围类对象的基础上,再创建成员内部类对象
* 这里已经存在外围类对象了,所以可以直接创建成员内部类对象.
*
* 2.外围类的静态成员方法中访问成员内部类成员
* 没有任何对象, 没有外围类对象
* 所以这里不存在成员内部类对象
* 所以想要访问它的成员,必须创建它的对象
* 如何创建呢?
* 要想得到成员内部类对象,必须先创建外围类对象。
* 在外围类对象的基础上,再创建成员内部类对象
* 对象创建完毕后,该咋访问就咋访问.
*
* 3.外部类访问成员内部类成员(多数情况下访问不到,不重要)
* 首先访问的全程都要受权限限制
* 其次外部类中,无论是成员方法还是静态方法
* 都没有区别
*
* 4.成员内部类访问外部类成员(不重要,受权限限制)
* 可以访问,该咋访问咋访问
* 受权限限制.
*
* 成员内部类和外围类是强依赖关系,成员内部类对象会持有外围类对象的引用
* 那么静态内部类和外围类之间,又有什么关系呢?
* 没有关系
* 静态内部类和外围类就是独立的两个类,只不过静态内部类借用外围类保护自己
*
* 静态内部类仍然定义在类的成员位置,它的语法是:
*
* [访问权限修饰符] class EnclosedClazz{
*
* [访问权限修饰符] static class NestedClazz{
* }
* }
*
* 静态内部类的自身特点
* 依然主要从以下几个角度分析:
* 1.访问权限修饰符
* 和成员内部类一样,有四种访问级别
* 四种皆可用
* 2.成员特点
* 静态内部类就是一个普通类放入另外一个类的类体中
* 所以它和普通类的成员没有任何区别
*
* 从这个角度出发,静态内部类相比较于成员内部类
* 静态内部类是更灵活的,不受外围类限制,单纯隐藏类
*
* 3.继承和实现
* 可以继承,可以实现,了解即可
*
* 静态内部类的访问特点:
* 主要从以下几个角度研究:
*
* 1.静态内部类内部访问外围类成员
* 直接创建外围类对象即可,访问不受权限限制.
*
* 2.外围类访问静态内部类成员
* 直接创建静态内部类对象即可,访问不受权限限制.
*
* 3.外部类访问静态内部类成员(了解即可)
* 全程受权限限制
* 而且注意:
* 这里访问静态内部类成员,不再需要创建外围类对象了
* 直接new创建静态内部类对象即可
* 语法:
* EnclosedClazz.NestedClazz nc = new EnclosedClazz.NestedClazz();
*
* 静态内部类访问外部类成员
*
* 局部内部类是定义在一个方法或者一个作用域里面的类
* 简单来说,将局部内部类看成是局部变量即可
* 该局部内部类的有效范围仅在作用域内部。
* (这意味着要创建它的对象,必须在作用域内部创建)
*
* 从语法和具体使用上看,局部内部类和成员内部类很相似
* 有点类似于直接把一个成员内部类放进局部位置,语法是:
*局部内部类语法
*
* class Inner{
* }
*
*
* 局部内部类自身特点
* 主要从以下几个角度分析:
* 1.访问权限修饰符
* 局部内部类的作用范围就仅在大括号内部
* 它不需要做权限控制
* 除此之外,它也不能用static修饰
* 这些都很类似于局部变量
*
* 2.成员特点
* 局部内部类的成员特点和成员内部类完全一模一样
* 没有static声明,但是可以定义不触发类加载的全局常量
*
* 3.继承和实现(重点)
* 开发中使用局部内部类主要的用途就是
* 用它继承/实现
*
* 在说明以下访问特点之前,我们要明确两个点:
* 1.局部内部类仅在定义它的作用域内部生效,这意味着即便是外围类
* 也不能任意访问它
* 只能在作用域内部去访问/使用它
*
* 2.内部类和外围类是"好兄弟"的原则,在局部内部类中发生了改变:
* 局部内部类仍然可以无条件访问外围类(不受限制)
* 外围类只能在作用域内部访问,作用域之外是不能直接访问这个局部内部类的
*
*局部内部类的访问特点,我们仍然主要从以下几个角度研究:
* 1.局部内部类内部访问外围类(重点)
* 可以正常访问,并且局部内部类没有静态声明
* 所以只能在成员方法中访问外围类
*
* (重点)局部内部类处在外围类的不同方法时,效果是不同的:
* a.外围类静态方法中的局部内部类
* 就是一个单纯的内部类,和外围类对象之间没有任何关系(类似于静态内部类)
*
* b.外围类成员方法中的局部内部类
* 这时局部内部类对象,会持有外围类对象的引用,作为它的成员变量(类似于成员内部类)
*
* 2.外围类访问局部内部类成员(一般)
* 在作用域内部创建对象,可以无条件访问
* 作用域之外不能直接访问局部内部类
*
* 3.外部类访问局部内部类成员(了解)
* 外部类肯定无法直接访问局部内部类
* 4.局部内部类访问外部类成员(了解)
* 可以访问,创建对象,受权限限制
*
* 以上语法,1是相对比较重要的,但是总体而言,都不是很常用.
*
* 局部内部类经常使用在以下两个场景中:
* 1.方法需要返回一个对象,返回值类型是引用数据类型时。
* 方法需要返回一个对象时,可以在方法的局部位置写一个 局部内部类 继承/实现外部的类/接口,创建对象后作为返回值。这是因为方法的返回值可以是返回值类型的对象,也可以是子类对象(当返回值类型是引用数据类型时)。
*
* 2.方法需要传入一个对象,形参数据类型是引用数据类型时。
*
* 方法需要传入一个对象实参时,可以在调用方法的位置定义一个 局部内部类 来继承/实现外部的类/接口,创建对象后作为方法的实参传入。这是因为方法的实参可以是形参类型的对象,也可以子类对象(当返回值类型是引用数据类型时)。
*
* 使用局部内部类的优点:
* 1.绝对对外界隐藏,封装。
* 2.相比较于传统的定义类,然后创建对象,它相对更加简洁省事。
*
* 缺点:
* 1.这个类是一次性的。
* 综上,假如在局部位置需要一次性的使用某个对象
* 可以使用局部内部类创建它
* 但是如果多次在不同的方法中使用,使用局部内部类就得不偿失了。
*
* 以上,局部内部类的语法还是有些麻烦了,这是局部内部类使用的最大限制
* 在实际开发中,很少直接使用局部内部类
* 因为匿名内部类,Lambda表达式语法更简洁,基本取代了它.
*