为什么要有继承性、继承性的好处?
1.减少代码冗余,提高代码复用性
2.便于功能的拓展
3.为多态的使用,提供基础
继承的概念
继承是java面向对象编程的基石,继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承性的格式: class A extends B{}
A:子类、派生类 subclass
B:父类、基类、superclass
2.1体现:一旦子类A继承父类之后,子类A中就获取了父类声明的所有的属性、方法
特别的父类中声明为Private的属性或方法,子类继承父类之后,仍然认为获取了父类私有的结构
只是因为封装性的影响,使得子类不能直接调用父类的结构
2.2 子类继承父类之后,还可以声明自己特有的属性和方法,实现功能的拓展
extends:延展、拓展
java中有关继承的规定
1.一个类可以被多个子类继承。
2.java中类的单继承性:一个类只能有一个父类
3.类可以多层继承
4.子类直接继承的父类 称为直接父类。间接继承的父类称为简介父类
5.子类继承父类后,就获取了直接父类和所有间接父类中声明的属性和方法
所有的java类除了Object类外,都直接或间接继承于Object类
所有的java类具有Object类声明的功能
代码实现
public class ExtendsTest {
public static void main(String[] args) {
Student student = new Student();
student.run();
student.eat();
}
}
class Person{
public void run() {
System.out.println("任何人都可以跑");
}
}
class Student extends Person{
public void eat() {
System.out.println("学生可以吃");
}
}
方法重写/方法覆盖
为什么要有方法的重写?
父类的某方法不是特别适合子类
重写的概念:
子类继承父类之后,可以对父类同名同参数的方法,进行覆盖操作,重写以后,当创建子类对象以后,通过子类对象调用父类的同名同参数的方法,实际执行的是子类重写父类的方法
重写的规则
方法的声明: 权限修饰符 返回值类型 方法名(形参){
//方法体 }
子类重写的方法名和形参列表与父类被重写的方法名和形参列表相同
子类重写的方法权限修饰符不小于父类被重写方法的权限修饰符
特殊情况,子类不能重写父类中声明为private权限的方法
返回值类型:
父类被重写的返回值类型是void,则子类重写的方法的返回值类型只能是void
父类被重写的返回值类型是A类,则子类重写的方法的返回值类型只能是A类或A类的子类
父类被重写的返回值类型是基本数据类型,则子类重写的方法的返回值类型只能是相同的基本数据类型
方法体是不同的,如果是相同的,那么就没必要再重写
子类重写的方法抛出异常类型不大于父类被重写的异常类型
子类和父类中同名同方法都声明为static才考虑重写
代码实现
//继承之方法的重写
public class OverrideTest {
public static void main(String[] args) {
Student1 student1 = new Student1();
student1.run();
student1.eat();
}
}
class Person1{
public void run() {
System.out.println("任何人都可以跑");
}
}
class Student1 extends Person1 {
public void run() {
System.out.println("学生可以跑");
}
public void eat() {
System.out.println("学生可以吃");
}
}
我们可以看到子类和父类当中都有run方法,而我们实际调用的却是子类自己的run方法,这就是方法的覆盖,子类通过重写和父类一样的方法实现方法的覆盖。
重载和重写的区别(面试题)
答:方法的重写Overriding和重载Overloading是Java多态性的不同表现。 重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。
子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。
如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。
super关键字的使用
1.super理解为:父类的
2.super可以调用:属性、方法、构造器
3.super的使用:调用属性和方法
3.1我们在子类的方法或构造器中,通过使用"super.属性"或"super.方法"的方式,显式调用父类中声明的属性或方法,通常情况下,习惯省略"super"
3.2特殊情况:当子类重写了父类中的方法以后,我们想在子类方法调用父类被重写的方法,必须用"super.方法",表面调用的是父类的方法
4.super调用构造器
4.1 在子类构造器中显式的使用"super(形参列表)"的方式,调用父类的构造器
4.2"super(形参列表)"的使用,必须生命在子类构造器的首行
4.3我们在类的构造器中,针对"this(形参列表)"或"super(形参列表)"只能2选1
4.4首行没写"this(形参列表)"或"super(形参列表)",默认使用"super(形参列表)"
4.5在类的多个构造器中,至少有一个类的构造器使用了"super(形参列表)"
类的加载顺序
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
先来想一下这段代码具体的执行过程,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。