Java
继承
面向对象特征
OPP 特征二:继承性 方法的重写 四种访问权限修饰符 关键字: super 子类对象实例化过程 OPP 特征三:多态性 继承性
一:继承性的好处
减少代码的冗余,提高了代码的复用性 便于功能的扩展 为之后多态性的使用,提供了前提 二:继承性的格式: class A extends B{} A: 子类,派生类,subclass B:父类,超类,基类,superclass
体现:一旦子类 A 继承父类 B 以后,子类 A 中就获取了父类 B 中声明的所有的属性和方法。 特别的,父类中声明为 private 的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。 只有因为封装性的影响,使得子类不能直接调用父类的结构而已。
子类继承父类以后,还可以声明自己特有的属性或方法,实现功能的拓展。子类和父类的关系,不同于子集和集合的关系。 extends: 延展,扩展
三:Java 中关于继承性的规定:
一个类可以被多个子类继承。 Java 中类的单继承性:一个类只能有一个父类 子父类是相对的概念 子类直接继承的父类,称为:直接父类,间接继承的父类称为:间接父类 子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法 四:
如果我们没有显式的声明一个类的父类的话,则此类继承于 java.lang.Object 类 所有的 java 类 (除 java.lang.Object 类之外)都直接或间接的继承于 java.lang.Object 类 意味着,所有的 java 类具有 java.lang.Object 类声明的功能。
重写
定义 在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
要求 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限。
注意:子类不能重写父类中声明为 private 权限的方法
子类方法抛出的异常不能大于父类被重写方法的异常
注意: 子类与父类中同名同参数的方法必须同时声明为非 static 的 (即为重写),或者同时声明为 static 的(不是重写)。因为 static 方法是属于类的,子类无法覆盖父类的方法。
具体说明
重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法
重写的规定:
方法的声明:权限修饰符 返回值类型 方法名 (形参列表) { //方法体 }
约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
② 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
特殊情况:子类不能重写父类中声明为 private 权限的方法
③ 返回值类型:
父类被重写的方法的返回值类型是 void,则子类重写的方法的返回值类型只能是 void
父类被重写的方法的返回值类型是 A 类型,则子类重写的方法的返回值类型可以是 A 类或 A 类的子类
父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法的返回值必须是相同的级别数据类型 (比如:double),则子类重写的方法的返回值类型必须是相同的级别数据类型 (必须是 double)
④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
多态
多态性,是面向对象中最重要的概念,在 JAVA 中的体现: 对象的多态性: 父类的引用指向子类的对象 可以直接应用在抽象类和接口上
Java 引用变量有两个类型:编译时类型 和 运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。 若编译时类型和运行时类型不一致,就出现了对象的多态性 (Polymorphism) 多态情况下,"看左边": 看的是父类的引用 (父类中不具子类特有的方法) "看右边": 看的是子类的对象(实际运行的是子类重写父类的方法)
理解多态性:可以理解为一个事物的多种形态。
何为多态性:对象的多态性:父类的引用指向子类的对象 (或子类的对象赋给父类的引用)
多态的使用:虚拟方法调用 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。 总结:编译,看左边; 运行,看右边。
多态性的使用前提:1.类的继承关系,2.方法的重写
对象的多态性:只话用于方法,不适用于属性 (编译和运行都看左边)
若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里能同名方法,系统将不可能把父类里的方法转移到子类中。编译看左边,运行看右边。
对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量。编译运行都看左边。
垃圾回收
新生代和老年代
在 JVM 运行的时候,最核心的内存区域,其实就是堆内存,在这里会放各种系统中创建出来的对象。
而且堆内存里通常都会划分为新生代和老年代两个内存区域,对象一般来说都是优先放在新生代的。 通常来说新生代会有一块 Eden 区域用来创建对象,默认占据 80% 的内存,还有两块 Survivor 区域用来放垃圾回收后存活下来的对象,分别占据 10% 的内存。
Young GC
在年轻代(也可以叫做新生代)快要塞满的时候,就会触发年轻代 gc(Young GC),也就是对年轻代进行垃圾回收,需要把年轻代里的垃圾对象都给回收掉。
一旦要对新生代进行垃圾回收了,** 此时一定会停止系统程序的运行 **,不让系统程序执行任何代码逻辑了,这个叫做 “Stop the World” 此时只能允许后台的垃圾回收器的多个垃圾回收线程去工作,执行垃圾回收。 由于在进行垃圾回收的时候必须停止系统程序的运行,导致了基于 JVM 运行的系统最害怕的系统卡顿问题。
新生代采用的复制算法效率极高,因为新生代里存活的对象很少,只要迅速标记出这少量存活对象,移动到 Survivor 区,然后回收掉其他全部垃圾对象即可,速度很快。
Young GC 对系统的影响
其实年轻代 gc 几乎没什么好调优的,因为它的运行逻辑非常简单,就是 Eden 一旦满了无法放新对象就触发一次 gc。 因此,Young GC 对系统影响通常来说是不大的。
一般来说,真要说对年轻代的 gc 进行调优,只要你给系统分配足够的内存即可,核心点还是在于堆内存的分配、新生代内存的分配。 内存足够的话,通常来说系统可能在低峰时期在几个小时才有一次新生代 gc,高峰期最多也就几分钟一次新生代 gc。而一次新生代 gc 可能也就耗费几毫秒、几十毫秒。