在面向对象中,类可以使用关键字extends继承另一个类,被继承的类叫父类,继承的类叫子类,子类自动拥有父类的属性和方法。
语法:
public class 子类名 extends 父类名{
}
注意:
- 子类继承父类中(除private类型外)所有的属性和方法
- 父类中的private的属性和方法,本质上是被继承了,但不能被子类对象直接访问,所以,在这里不认为被子类继承了。
- 继承在java中是单一继承,每一个类只能有一个父类
- 同一个类可以被多个子类继承
- C继承了B,B继承了A,那么C也继承了A中的属性和方法
继承中的实例化过程
- 子类实例化过程中,先实例化父类,再实例化子类,也就是先调用父类的构造方法,然后再调用子类的构造方法
- super 指向父类的引用,
- 如果子类中定义了有参的构造方法,而父类没有提供无参的构造方法(若父类有无参的构造方法,因为编译器会自动提供父类的无参构造方法,所以编译不会出错),这时在子类中的有参的构造方法中就必须手动调用父类的有参构造方法。
- 使用super(参数列表)来调用,super()这句必须写在子类构造器中的第一行。
- 如果调用的父类中的无参构造方法,可以写super(),如果不写,编译器会默认加上super()。
- 如果子类中调用父类中不存在的构造方法,则会编译报错。
- this 指向本类的引用
- this()表示调用本类中无参的构造方法。
- this(参数列表)表示调用本类中参数列表相符的构造方法。
- 构造方法中this()和super()不可以同时出现。
方法的覆盖(Override)
又叫方法的重写,是指子类中对于继承来的父类中的方法进行改写,只在子类中产生方法的覆盖。
是在子类中覆盖继承过来的父类的同名方法,重写需要满足的要求:
- 方法名相同
- 参数列表相同
- 返回值类型相同
- 子类中重写的方法的权限范围不能小于父类中被重写方法的权限范围,否则编译出错
- 可以在方法名上方加注解@Override,也可以不加注解,建议加上,可提高可读性、减少错误。
最后,附上一个继承的例子(不是写在同一个文件中)。
//*************************父类************************
public class SuperTest {
private String name = "supertest";
static {
System.out.println("The static in SuperTest.");
}
public SuperTest() {
System.out.println("This SuperTest().");
sayHello();
print();
}
public void sayHello() {
System.out.println("Hello, I am superTest.");
}
public void print() {
System.out.println(name);
}
}
//*************************子类************************
public class SubTest extends SuperTest{
private String name="subtest";
static {
System.out.println("The static in SubTest.");
}
public SubTest() {
System.out.println("This SubTest().");
sayHello();
print();
}
@Override
public void sayHello() {
System.out.println("Hello,I am SubTest.");
}
public void print() {
System.out.println(name);
}
}
//*************************测试类************************
public class Test {
public static void main(String[] args) {
new SubTest();
}
}
输出:
The static in SuperTest.
The static in SubTest.
This SuperTest().
Hello,I am SubTest.
null
This SubTest().
Hello,I am SubTest.
subtest
执行顺序是:父类静态变量和父类static代码块->子类静态变量子类static代码块->父类非静态变量和父类构造方法->子类非静态变量和子类构造方法。
要注意的是,在执行父类构造方法时,调用的sayHello()方法,输出的是子类重写后的内容。
同样的,变量也是如此,在调用父类构造方法时,print()方法输出的是子类中的变量,但由于子类中的变量name还未初始化,所以输出null。