java_day3

继承

例如:
人 类:姓名,性别,年龄,打印信息的方法
学生类:姓名,性别,年龄,学校,打印信息的方法
工人类:姓名,性别,年龄,工种,打印信息的方法
教师类:姓名,性别,年龄,科目,打印科目的方法

如果硬写,代码会有很多重复,为了解决这类问题,java提供了继承的特性

人类 -> 父类

学生类

工人类

  • 此处的多个类称为子类,单独的这个类称为父类(基类或超类)
  • 类的继承语法规则:class Subclass extends Superclass{}
  • 继承的出现让类与类之间产生了关系,提供了多态的前提
  • 不要仅为了获取其他类中的某个功能而去继承
  • 子类不是父类的子集,而实对父类的“扩展”。

继承规则

  • 子类不能使用父类的私有成员

  • java只支持单继承,不允许多重继承

    • 一个子类只能有一个父类

    • 一个父类可以派生出多个子类

      • class SubDemo extends Demo {} //correct
      • class SubDemo extends Demo1, Demo2... //error

方法的重写

定义:在子类中可以根据需要对父类中继承来的方法进行改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。

要求:

  • 重写的方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型

    • 也就是只能重写编写方法体的代码
  • 重写的方法不能使用比重写方法更严格的访问权限

    • 如果父类是public的,子类重写的时候就不能使用缺省、private等
  • 重写和被重写的方法必须同时为static的,或同时为非static的

  • 子类方法抛出的异常不能大于父类被重写方法的异常

重载与重写

重载:一个类有多个同名方法
重写:子类可以重新写父类的方法,覆盖父类的方法

父子类与访问修饰符的关系

修饰符类内部同一个包子类除了前面之外的任何地方
privateyes   
(缺省)yesyes  
protectedyesyesyes 
publicyesyesyesyes

如果子类和父类在同一个包下,那么对于父类的成员,只要不是私有的,那就都可以使用。
如果子类和父类不在同一个包下,那么子类只能使用父类中protected和public修饰的方法和成员变量

关键字super

  • 在java类中使用super调用父类中的指定操作

    • super可用于访问父类中定义的属性
    • super可用于调用父类中定义的成员方法
    • super可用于在子类构造方法中调用父类的构造器
  • 注意

    • 尤其当子父类出现同名成员时,可以用super来区分
    • super的追溯不仅限于直接父类
    • super和this的用法很像,this代本类对象的引用,super代表父类的内存空间的标识

调用父类的构造器

  • 子类中所有的构造器默认都会访问父类中空参数的构造器
  • 当父类中没有空参数构造器时,子类的构造器必须通过this(参数列表)或super(参数列表) 语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行,super要放在第一行
  • 如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译会出错。

this和super的区别

区别点thissuper
访问属性访问本类中的属性,如果本类中没有就从父类中找访问父类中的属性
调用方法访问本类中的方法直接访问父类中的方法
调用构造器调用本类构造器,必须要放在构造器的首行调用父类构造器,必须放在子类构造器的首行
特殊表示当前对象无此概念

java简单对象的实例化过程

Person p = new Person();
step 1: 在方法区加载person.class
step 2: 在栈中声明变量p
step 3: 在堆内存中开辟空间,分配地址;
step 4: 在对象空间中,对对象中的属性进行默认初始化
step 5: 构造函数方法进栈,进行初始化
step 6: 初始化完毕后,将堆内存中的地址赋值给引用变量,构造方法出栈

java子类对象实例化的过程

step 1: 先加载父类Person.class,再加载子类Student.class
step 2: 在栈中分配空间,声明变量stu
step 3: 在堆内存中开辟空间,分配地址
step 4: 并在对象空间中,对对象中的属性(包括父类的属性)进行默认初始化,int为0,string为null
step 5: 子类构造方法进栈
step 6: 显示初始化父类属性
step 7: 父类构造方法进栈
step 8: 显示初始化子类的属性
step 9: 初始化完毕后,将堆内存中的地址赋值给引用变量,子类构造方法出栈

多态

  • 方法的重载和重写
  • 对象的多态性——可以直接应用在抽象类和接口上

java引用变量有两个类型,编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定的,运行时类型由实际赋给该变量的对象决定

若编译时类型和运行时类型不一致,就出现多态

子类可以看作特殊的父类,所以父类类型的引用可以指向子类对象:向上转型(upcasting)

一个引用类型变量如果声明为父类的类型,但实际引用的却是子类的对象,那么这个变量就不能访问子类中添加的属性或者方法

虚拟方法的调用

多态总结

  • 前提

    • 需要存在继承或者实现关系
    • 需要有覆盖操作
  • 成员方法

    • 编译时:要查看引用变量所属类中是否有所调用的方法
    • 运行时:调用实际对象的类中的重写方法
  • 成员变量

    • 不具备多态性,只看引用变量所属的类
  • 子类继承父类

    • 若子类重写了父类方法,那么系统将不可能把父类中的方法转移到子类中
    • 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量

instanceof操作符

x instanceof A:检验x是否为类A的对象,返回值为boolean类型

Object类

  • object类是java类中的根父类,基类
  • 如果在类的声明中未使用extends关键字指定其父类,则默认父类为object类

主要用途:

方法名称类型描述
public Object()构造构造方法
public boolean equals(Object obj)普通对象比较
public int hashCode()普通取得Hash码
public String toString()普通对象打印时调用

立志成为一名攻城狮