继承
例如:
人 类:姓名,性别,年龄,打印信息的方法
学生类:姓名,性别,年龄,学校,打印信息的方法
工人类:姓名,性别,年龄,工种,打印信息的方法
教师类:姓名,性别,年龄,科目,打印科目的方法
如果硬写,代码会有很多重复,为了解决这类问题,java提供了继承的特性
人类 -> 父类
xxxxxxxxxx
public class Person {
int age;
String name;
int sex;
public void showInfo() {
System.out.println(this.age);
System.out.println(this.name);
System.out println(this.sex);
}
}
学生类
xxxxxxxxxx
public class Student extends Person {
String school;
public void showInfo() {
System.out.println(this.age);
System.out.println(this.name);
System.out println(this.sex);
System.out println(this.school);
}
}
工人类
xxxxxxxxxx
public class worker extends Person {
String workKind;
public void showInfo() {
System.out.println(this.age);
System.out.println(this.name);
System.out println(this.sex);
System.out println(this.workKind);
}
}
- 此处的多个类称为子类,单独的这个类称为父类(基类或超类)
- 类的继承语法规则:class Subclass extends Superclass{}
- 继承的出现让类与类之间产生了关系,提供了多态的前提
- 不要仅为了获取其他类中的某个功能而去继承
- 子类不是父类的子集,而实对父类的“扩展”。
继承规则
子类不能使用父类的私有成员
java只支持单继承,不允许多重继承
一个子类只能有一个父类
一个父类可以派生出多个子类
- class SubDemo extends Demo {} //correct
- class SubDemo extends Demo1, Demo2... //error
方法的重写
定义:在子类中可以根据需要对父类中继承来的方法进行改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
要求:
重写的方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型
- 也就是只能重写编写方法体的代码
重写的方法不能使用比重写方法更严格的访问权限
- 如果父类是public的,子类重写的时候就不能使用缺省、private等
重写和被重写的方法必须同时为static的,或同时为非static的
子类方法抛出的异常不能大于父类被重写方法的异常
xxxxxxxxxx
//父类
public void setInfo(int age, String name, int sex) {
this.age = age;
this.name = name;
this.sex = sex;
}
//子类重写
public void setInfo(int age, String name, int sex) {
//代码块随便写
System.out.println(age);
System.out.println(name);
System.out.println(sex);
}
重载与重写
重载:一个类有多个同名方法
重写:子类可以重新写父类的方法,覆盖父类的方法
父子类与访问修饰符的关系
修饰符 | 类内部 | 同一个包 | 子类 | 除了前面之外的任何地方 |
---|---|---|---|---|
private | yes | |||
(缺省) | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
如果子类和父类在同一个包下,那么对于父类的成员,只要不是私有的,那就都可以使用。
如果子类和父类不在同一个包下,那么子类只能使用父类中protected和public修饰的方法和成员变量
关键字super
在java类中使用super调用父类中的指定操作
- super可用于访问父类中定义的属性
- super可用于调用父类中定义的成员方法
- super可用于在子类构造方法中调用父类的构造器
注意
- 尤其当子父类出现同名成员时,可以用super来区分
- super的追溯不仅限于直接父类
- super和this的用法很像,this代本类对象的引用,super代表父类的内存空间的标识
调用父类的构造器
- 子类中所有的构造器默认都会访问父类中空参数的构造器
- 当父类中没有空参数构造器时,子类的构造器必须通过this(参数列表)或super(参数列表) 语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行,super要放在第一行
- 如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译会出错。
this和super的区别
区别点 | this | super |
---|---|---|
访问属性 | 访问本类中的属性,如果本类中没有就从父类中找 | 访问父类中的属性 |
调用方法 | 访问本类中的方法 | 直接访问父类中的方法 |
调用构造器 | 调用本类构造器,必须要放在构造器的首行 | 调用父类构造器,必须放在子类构造器的首行 |
特殊 | 表示当前对象 | 无此概念 |
java简单对象的实例化过程
Person p = new Person();
step 1: 在方法区加载person.class
step 2: 在栈中声明变量p
step 3: 在堆内存中开辟空间,分配地址;
step 4: 在对象空间中,对对象中的属性进行默认初始化
step 5: 构造函数方法进栈,进行初始化
step 6: 初始化完毕后,将堆内存中的地址赋值给引用变量,构造方法出栈
java子类对象实例化的过程
xxxxxxxxxx
public class Person {
public Person() {
}
int age = 1;
String name = "zhangsan";
itn sex = 0;
}
public class Student extends Person() {
public Student() {
suepr();
}
String school;
}
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引用变量有两个类型,编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定的,运行时类型由实际赋给该变量的对象决定
若编译时类型和运行时类型不一致,就出现多态
xxxxxxxxxx
Person p = new Person(); //正常现象
Student stu = new Student(); //正常现象
Person e = new Student(); //使用子类对象初始化父类对象,多态了;父类的引用对象,可以指向子类的实例
Person p = new Person();
p = new Student()
//当前这个引用对象p引用的是student这个实例
子类可以看作特殊的父类,所以父类类型的引用可以指向子类对象:向上转型(upcasting)
一个引用类型变量如果声明为父类的类型,但实际引用的却是子类的对象,那么这个变量就不能访问子类中添加的属性或者方法
虚拟方法的调用
xxxxxxxxxx
Person e = new Student();
e.getInfo();
//这里调用的getInfo是Student里面的
多态总结
前提
- 需要存在继承或者实现关系
- 需要有覆盖操作
成员方法
- 编译时:要查看引用变量所属类中是否有所调用的方法
- 运行时:调用实际对象的类中的重写方法
成员变量
- 不具备多态性,只看引用变量所属的类
子类继承父类
- 若子类重写了父类方法,那么系统将不可能把父类中的方法转移到子类中
- 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量
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() | 普通 | 对象打印时调用 |
Comments | NOTHING