目录
一、继承的概念
狗是一种动物,有名字和年龄,可以汪汪叫;猫是一种动物,有名字和年龄,可以喵喵叫......每种动物都有名字和年龄,那我们每定义一种动物就要定义名字和年龄就会重复定义效率减慢。考虑定义一个动物类,里面放有名字、年龄成员变量,而在定义狗、猫等类时直接使用动物类中的成员变量,就可以减少代码的重复定义,且在新定义的类中可以加入独有的特性,而这就是继承的思想。其中的动物类可以称为父类/基类/超类,狗、猫等类可以称为子类/派生类。
继承主要解决的问题是:共性的抽取,实现代码复用。
二、继承的语法
修饰符 class 子类 extends 父类{
子类的成员变量;
子类的成员方法;
}
eg:
class Animal{ //父类
public String name;
public int age;
public void eat(){
System.out.println(name+"吃饭");
}
}
class Dog extends Animal{ //子类继承父类
public void barks(){
System.out.println(name+"汪汪叫");
}
}
public class test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.name="阿黄";
dog.age=2;
dog.eat();
dog.barks();
}
}
三、子类中访问父类的成员变量/方法
1.子类和父类中不存在同名的成员变量/方法(直接访问)
上述代码dog.name 属于子类(Dog类)直接访问父类(Animal类)中的成员变量(name,age)、成员方法(eat())
2.子类和父类中存在同名的成员变量/方法(优先访问子类的成员变量/方法)
eg:
class Animal{
public String name;
public int age;
public void eat(){
System.out.println("父类的eat:"+name+"吃饭");
}
public void method(){
System.out.println(this.name+" "+this.age);
}
}
class Dog extends Animal{
public String name;
public int age;
public void eat(){
System.out.println("子类的eat:"+name+"吃饭");
}
public void barks(){
System.out.println(name+"汪汪叫");
}
}
public class test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.name="阿黄";
dog.age=2;
dog.eat();
dog.method();
}
}
输出结果:
根据输出结果可知优先访问子类的成员变量(name、age)、成员方法(eat())
3.子类和父类中存在相同的成员变量/方法,想实现优先访问父类的成员变量/方法(super关键字)
存在同名的成员变量,实现访问父类的成员变量:子类方法中,super.成员变量名;
存在同名的成员方法,实现访问父类的成员方法:子类方法中,super.成员方法名();
eg:
class Animal{
public String name;
public int age;
public void eat(){
System.out.println("父类的eat:"+name+"吃饭");
}
public void method(){
System.out.println(this.name+" "+this.age);
}
}
class Dog extends Animal{
public String name;
public int age;
public void eat(){
System.out.println("子类的eat:"+name+"吃饭");
}
public void barks(){
System.out.println(name+"汪汪叫");
}
public void method2(){
super.name="阿黄";
super.age=2;
super.eat();
super.method();
}
}
public class test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.method2();
}
}
输出结果:
根据结果可知访问类父的成员变量(name、age)、成员方法(eat()),super只能在非静态方法中使用。
四、子类构造方法
子类对象在构造时,需要先调用父类的构造方法,然后执行子类的构造方法,且调用的父类的构造方法语句必须是子类的构造方法中的第一行语句。
eg:
注意事项:①若父类的构造方法无参数或者java默认的构造方法,则在子类构造方法第一行可以省略super();②若父类的构造方法有参数,则子类必须调用父类的构造方法;③父类可以有多个构造方法,但子类只能调用其中一个;④super()和this()不能同时出现在子类构造方法中。
五、有关继承的初始化
eg:
class Animal{
public String name;
public int age;
public Animal() {
System.out.println("这是父类的构造方法!!!");
}
static {
System.out.println("这是父类的静态代码块!!!");
}
{
System.out.println("这是父类的构造代码块!!!");
}
}
class Dog extends Animal{
static {
System.out.println("这是子类的静态代码块!!!");
}
{
System.out.println("这是子类的构造代码块!!!");
}
public Dog() {
System.out.println("这是子类的构造方法!!!");
}
}
public class test {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println("===================================");
Dog dog1 =new Dog();
}
}
上述代码的执行顺序大家认为是什么?
输出结果:
结论:①继承关系上代码块的执行顺序:父类静态代码块→子类静态代码块→父类构造代码块→父类构造方法→子类构造代码块→子类构造方法;②不管生成多少对象,父类静态代码块和子类静态代码块只执行一次。
六、访问限定符的访问权限
具体就不举例子了,大家可以建立不同的包和不同的子类,就可以验证结论了。
七、final关键字
1.final修饰变量,表示该变量是常量,不能被修改;
eg:
2.final修饰类,表示此类不能被继承;
eg:
3.final修饰方法,表示此方法不能被重写(多态解释重写)