继承包含的概念:
继承的本质:复用已存在的方法和域
一、概念:
继承是java面向对象编程的基石,继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
public class Person { public void run() { System.out.println("任何人都可以跑。。。"); } } class Student extends Person{ private void eat() { System.out.println("学生正在吃。。。。"); } public static void main(String[] args) { Student student = new Student(); student.run(); student.eat(); } }
由以上代码我们可以看出:关键字extends表明正在构造的新类Student派生于一个已经存在的类Person,已存在的类称为超类或者父类;子类称为子类。我们还可以看出子类可以调用父类的方法,而且子类可以拥有自己的方法,功能比超类更丰富
(子类可以调用父类的方法,但是父类不能调用子类的方法)
二、z方法重载和方法重写
1.方法重载
2.方法覆盖
在有些时候,子类当中需要调用父类当中的方法,但是父类当中的方法对子类来说并不一定适用。这个时候我们就需要使用到方法的覆盖。例如
public class Person { public void run() { System.out.println("任何人都可以跑。。。"); } } class Student extends Person{ public void run() { System.out.println("这个学生在跑。。。"); } private void eat() { System.out.println("学生正在吃。。。。"); } public static void main(String[] args) { Student student = new Student(); student.run(); student.eat(); } }
我们可以看到子类和父类当中都有run方法,而我们实际调用的却是子类自己的run方法,这就是方法的覆盖,子类通过重写和父类一样的方法实现方法的覆盖。
//方法的覆盖 //子类和父类当中都有相同的方法, //子类通过重写父类方法实现方法的覆盖 public void getRun() { System.out.println("所有小猫杜能跑。。。。"); } //一个方法的签名是由方法名称以及参数列表所组成 //方法的重载是指在一个类当中有相同的方法名不同的参数列表 public void getRun(int s) { System.out.println("所有小猫杜能跑。。。。"+s); } public static void main(String[] args) { Cat cat = new Cat(); cat.getRun(); }
重载和重写的区别
重载: 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序
不同,方法返回值和访问修饰符可以不同,发生在编译时。
重写: 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父
类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类
方法访问修饰符为 private 则子类就不能重写该方法。
三、super关键字
super 关键字有两个用途:一是调用超类的方法,二是调用超类的构造器。调用构造器语句的时候只能作为另一个构造器的第一条语句出现。
四、继承层次
Java只支持单继承
继承并不限于一个层次。
public class Person {
public void run() {
System.out.println("任何人都可以跑。。。");
}
}
class Student extends Person{
public void run() {
super.run();
System.out.println("这个学生在跑。。。");
}
private void eat() {
System.out.println("学生正在吃。。。。");
}
public static void main(String[] args) {
Student student = new Student();
student.run();
student.eat();
}
}
class XiaoMing extends Student{
}
class XiaoHong extends Student{
}
由一个公共超类派生出来的所有类的集合被称为继承层次,在继承层次当中,从某个特定的类到其祖先的路径被称为继承链,但是一定要注意java是单继承的。
Person的继承层次
五、类的加载顺序
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()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。
public class Demo { public Demo(String aa){ System.out.println("===="+aa); } static { System.out.println("11"); } public static Demo demo = new Demo("+++"); static { System.out.println("22"); } } class Test{ public static void main(String[] args) { Demo demo = new Demo("----"); } }
输出:
11
====+++
22
====----
所有的静态的类的初始化都交给类的第一个对象去执行