一、面向对象特征二:继承

IS-A关系

IS-A就是说:一个对象是另一个对象的一个分类

HAS-A关系

HAS-A代表类和它的成员之间的从属关系

继承性的好处

①减少了代码的冗余,提高了代码的复用性
②便于功能的扩展
③为之后多态性的使用,提供了前提
image.png

继承性的格式

class A extends B {}
A:子类、派生类、subclass
B:父类、超类、基类、superclass

体现

一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的结构(属性、方法)

特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已。

子类继承父类以后,还可以声明自己特有的属性或方法,实现功能的拓展。

子类和父类的关系,不同于子集和集合的关系 extends:延展、扩展

Java中继承性的规定(说明)

①一个类可以被多个子类继承
②Java中类的单继承性:一个类只能有一个父类
③多层继承:子父类是相对的概念
④子类直接继承的父类称为直接父类,间接继承的父类称为间接父类
⑤子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法

Object类

如果没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
所有的Java类(除Object)都直接或间接的继承于java.lang.object类

意味着所有的java类具有java.lang.Object所具有的功能

二、方法的重写(override/overwrite)

定义

子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作

应用

重写以后,当创建子类以后,通过子类对象调用字符类中的同名同参数的方法时,实际执行的是子类重写父类的方法

重写的规定

预定俗称:子类中的叫重写的方法,父类中的叫被重写的方法

方法的声明: 权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型 { //方法体 }

子类和父类的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)

权限修饰符

①子类重写的方法的方法名和形参列表与父类被重写的方法名和形参列表相同
②子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符

特殊情况:子类不能重写父类的private权限的方法

返回值类型

③父类被重写的方法的返回值是void,子类重写的方法的返回值类型只能是void
④父类被重写的方法的返回值类型是A类(引用数据类型),则子类重写方法的返回值类型可以是A类或者A类型的子类(引用数据类型)
⑤父类被重写的方法的返回值类型是基本数据类型(比如double),则子类重写方法的返回值类型必须是相同的基本数据类型(必须是double)

异常

⑥子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放到异常处理再说)

区分方法的重载与重写

说明白重载是什么、重写是什么

①二者的概念
重载:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可
重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
②重载和重写的具体规则
重载:两同一不同(https://www.yuque.com/sp1bgo/vmn0df/egg63s#FOoD7
重写:https://www.yuque.com/sp1bgo/vmn0df/egg63s#UOpSk
③重载不表现为多态性,重写表现为多态性

从编译和运行的角度看 重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数列表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。他们的调用地址在编译期就绑定了。Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法 对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”

而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这成为“晚绑定”或的“动态绑定”

三、关键字:super

理解

父类的xxx

使用

用来调用属性、方法、构造器

属性和方法

①我们可以在子类的方法或构造器中。通过使用 “super.属性” 或 “super.方法” 的方式,显式的调用父类中声明的属性或方法。但是通常情况下,我们习惯省略 “super”
②特殊情况:当子类和父类定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用 “super.属性” 的方式,表明调用的是父类中声明的属性
③特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用 “super.方法” 的方式,表明调用的是父类中被重写的方法

构造器

④我们可以在子类的构造器中显式的使用 “super(形参列表)” 的方式,调用父类中声明的指定的构造器
⑤”super(形参列表)” 的使用,必须声明在子类构造器的首行!
⑥我们在类的构造器中,针对于 “this(形参列表)” 或 “super(形参列表)” 只能二选一,不能同时出现
⑦当我们在构造器的首行,没有显式的声明 “this(形参列表)” 或 “super(形参列表)” ,则默认调用的是父类中空参的构造器 “super(形参列表)”
⑧在类的多个构造器中,至少有一个类的构造器中使用 “super(形参列表)” ,调用父类中的构造器

四、子类对象实例化全过程

从结果上看

子类继承父类以后,就获取了父类中声明的属性或方法
创建子类对象,在堆空间中,就会加载所有父类中声明的属性

从过程上看

image.png
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器。进而调用父类的父类的构造器,直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有父类的结构,所以才可以看到内存中有父类的结果,子类对象才可以考虑进行调用

虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象

五、面向对象的特征三:多态

定义

父类的引用指向子类的对象(或子类的对象赋给父类的引用)

理解:一个事物的多种形态 ①实现代码的通用性 ②Object类中equals(Object obj){}的实现体现了多态性 JDBC:使用java程序操作(获取数据库连接、CRUD)数据库(Mysql、Oracle、DB2、SQL Server) ③为了抽象类、接口的使用(抽象类、接口不能实例化)

使用(虚拟方法调用)

有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法

编译,看左边;运行,看右边

对象的多态性,只适用于方法,不适用于属性

全部看左边

多态性的使用前提

①需要有类的继承关系
②需要有方法的重写

虚拟方法调用再说明

正常方法调用

  1. Person e = new Person();
  2. e.getInfo();
  3. Student s = new Student();
  4. s.getInfo();

虚拟方法调用(多态情况下)

子类中定义了与父类同名同参数(重写)的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的

  1. Person e = new Student();
  2. e.getInfo(); //调用Student类的getInfo()方法

编译时类型和运行时类型

编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法

动态绑定

向上转型与向下转型

image.png

向上转型

向上转型就是多态

向下转型

为什么使用向下转型
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明了父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。要使用子类特有的属性和方法只能通过向下转型来使用

如何实现向下转型
使用强制类型转换符

注意点
使用强转时,可能出现ClassCastException异常,为了避免在向下转型是出现该异常,我们在向下转型之前先进行 instanceof 的判断,一旦返回true,就进行向下转型。

instanceof 操作符

使用情景

使用强转时,可能出现ClassCastException异常,为了避免在向下转型是出现该异常,我们在向下转型之前先进行instanceof的判断,一旦返回true,就进行向下转型。

具体使用

a instanceof A:判断对象a是否是类A的实例。如果是返回true,不是返回false

如果类B是类A的父类,当 a instanceof A 返回 true ,则 a instanceof B 也返回 true

六、Object类的使用

定义

Object类是所有Java类的根父类

如果在类的声明中未使用extends关键字指明其父类,则默认父类未java.lang.Object类 Object类中的功能(属性、方法)就具有通用性 Object类只声明了一个空参构造器,无属性 常用方法 equals() / toString() / getClass() / hashCode() / clone() / finalize() / wait() / notify() / notifyAll()

equals() 方法

== 和 equals() 区别

== 运算符
可以使用在基本数据类型变量和引用数据类型变量中
基本数据类型:比较两个变量保存的数值是否相等(不一定类型要相同)
引用数据类型:比较两个对象的地址值是否相等,即两个引用是否指向同一个对象实体
equals() 方法(java.lang.Object类中的equals)

是一个方法,而非运算符,因此基本数据类型变量无法使用

Object类中 equals() 的定义

  1. public boolean equals(Object obj) {
  2. return (this == obj);
  3. }

Object类中定义的equals() 与 == 运算符的作用是相同的:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体 像String、Date、File、包装类等都重写了Object类中 equals() 方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的”实体内容”(实际内容,非地址值)是否相同

重写Object类的equals方法

重写的原则:比较两个对象的实体内容是否相同

  1. public class EqualsTest {
  2. public static void main(String[] args) {
  3. Person p1 = new Person(1);
  4. Person p2 = new Person(1);
  5. System.out.println(p1.equals(p2));
  6. }
  7. }
  8. class Person {
  9. private int age;
  10. Person(int age) {
  11. this.age = age;
  12. }
  13. @Override
  14. public boolean equals(Object obj) {
  15. if (this == obj) {
  16. return true;
  17. }
  18. if (obj instanceof Person) {
  19. return this.age == ((Person) obj).age;
  20. }
  21. return false;
  22. }
  23. }

toString() 方法

定义

Object类中的 toString() 方法返回对象的类名以及它的引用地址

当我们输出一个对象的引用时,实际上就是调用当前对象的 toString()

Object类中 toString() 的定义

  1. public String toString() {
  2. return getClass().getName() + "@" + Integer.toHexString(hashCode());
  3. }

像String、Date、File、包装类等都重写了Object类中的 toString() 方法,使得调用对象的 toString() 方法时,返回”实体内容”信息
自定义类也可以重写 toString() 方法,当调用此方法时,返回对象的”实体内容”

七、包装类(Wrapper)的使用

定义

针对八种基本数据类型定义相应的引用类型——包装类(封装类)
image.png

自动装箱与自动拆箱(5.0新特性)

自动装箱(基本数据类型——>包装类)

将基本数据类型直接赋值给对应的包装类引用变量

Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在-128~127范围内时,可以直接使用数组中的元素,不用再去new了。 目的:提高效率

自动拆箱(包装类——>基本数据类型)

将包装类的对象赋值给对应的基本数据类型变量

包装类、基本数据类型、String类的相互转化

由于有了自动装箱、自动拆箱,包装类与基本数据类型之间转换十分方便,干脆看成一个整体,因此重点关注两者如何转化String类

基本数据类型、包装类——>String

方式一:连接运算

  1. String str = 10 + "";

方式二:String.valueOf() 方法

  1. String str = String.valueOf(12.3f);

String——>基本数据类型、包装类

调用包装类的parseXxx(String s) 方法

除了Boolean,其余的包装类对应的方法可能会出现NumberFormetException异常

image.png