继承是面向对象里面很重要的概念,继承允许我们创建分等级层次的类。
//父类
public class People {
int age;
private String name;
int gender; //1表示男生 0表示女生
}
//子类
public class Student extends People {
int number;
}
-
被继承的类叫做父类,使用extends的叫做子类。
-
我们通常可以把很多重复的属性、方法放到一个父类当中,让子类继承父类的能力,可以提升代码的维护性、扩展性。
-
Java支持多层级继承,比如 LaoSun 继承了 Student,Student继承了People;
-
可以使用super关键字访问父类的方法或者属性:
//访问父类的构造方法,注意:需要写在子类构造方法的第一行
super(age, name, gender);
//访问父类的成员变量
super.name;
//访问父类的方法
super.getName();
- 如果父类有重载构造方法,那么在子类构造方法里也需要指定父类的构造方法是哪个
public class People {
//父类中重载了构造方法
public People(int age, String name, int gender) {
this.age = age;
this.name = name;
this.gender = gender;
}
}
public class Student extends People {
public Student(int number, int age, String name, int gender) {
//子类中需要指定父类的构造方法
super(age, name, gender);
this.number = number;
}
}
-
如果父类和子类的属性、方法冲突,子类会去找离他最近的那个属性或者方法。
-
子类可以拥有父类的非private方法和属性
子类对象可以被当成是父类对象来使用,比如说:
//被放到存放父类型的容器
ArrayList<People> peoples = new ArrayList<>();
Student laosun = new Student(10, 18, "老孙", 1);
peoples.add(laosun);
//被赋值给父类变量,注意:这种方式被称为向上转型
People laoli = new Student(13, 21, "老李", 0);
//同时,也有向下转型:把父类变量强制转为子类变量
Student stu = (Student) laoli;
//被传递到需要父类类型的方法中
public void addPeople(People p1){
peoples.add(p1);
}
多态
调用的父类的show,但实际执行,Java却知道分别是属于哪个子类,从而调用对应的show
public class People {
public String show() {
return null;
}
}
public class Student extends People {
//子类重写父类方法
@Override
public String show() {
String name = getName();
return "姓名:" + name + ",学号是" + number + ",年龄" + age + ",性别是" + gender;
}
}
People laoli = new Student(13, 21, "老李", 0);
//这里实际调用的是子类的show方法
System.out.println("你要查询的学生信息:" + laoli.show());
重写
要成功地重写父类中的方法,需要满足以下条件:
- 方法名称、参数列表必须相同:子类重写父类的方法时,方法名称和参数列表(包括参数类型、参数顺序和参数数量)必须与父类中被重写的方法完全相同。
- 访问权限不能更低:子类重写父类的方法时,访问权限(public、protected、默认(无修饰符)或private)不能低于父类中被重写的方法的访问权限。例如,如果父类中的方法是
protected
的,那么子类中的重写方法不能是private
的。 - 返回类型要兼容:子类重写父类的方法时,返回类型必须与父类中被重写的方法的返回类型相同或是其子类。在Java 5及以后的版本中,如果父类中的方法返回类型是泛型,子类重写的方法可以返回该泛型的子类。
- 子类重写的方法不能抛出比父类方法更广泛的检查型异常:检查型异常是编译器在编译时可以检查出来的异常。子类重写父类的方法时,可以抛出与父类方法相同的检查型异常,或者是父类方法抛出的检查型异常的子类。但是,子类重写的方法不能抛出新的检查型异常,除非这个异常是运行时异常(RuntimeException)或其子类。
- 父类中的方法不能为final:如果父类中的方法被声明为
final
,那么子类不能重写该方法。 - 父类中的方法不能为static:如果父类中的方法是静态的(
static
),那么子类不能重写该方法。但是,子类可以定义与父类静态方法相同名称和参数列表的静态方法,这被称为隐藏(Hiding),而不是重写。