Java继承

来源:互联网 发布:js invalid signature 编辑:程序博客网 时间:2024/06/06 11:42

继承的定义

继承可以看成是类与类之间的衍生关系。比如狗类是动物类,牧羊犬类又是狗类。于是我们可以说狗类继承了动物类,而牧羊犬类就继承了狗类。于是狗类就是动物类的子类(或派生类),动物类就是狗类的父类(或基类)。

所以继承需要符合的关系是:is-a,父类更通用,子类更具体。

我们创建一个类需要它来继承某一个类的语法:

class 子类 extends 父类

例如我们定义了一个 Animal 类,我们在创建一个 Dog 类,我们需要它继承 Animal 类

class Dog extends Animal {    ...}

接下来我们就来练习一下吧!

我们先创建一个父类 Animal

package com.shiyanlou;public class Animal {    public int legNum;     //动物四肢的数量    //类方法    public void bark() {        System.out.println("动物叫!");    }}

接下来创建一个子类,我们可以自己输入代码,也可以利用 Eclipse 帮我们自动建立继承关系。

1、点击创建 class 类

2、输入子类名称,点击Superclass后面的Browse...寻找父类,与之建立继承关系

子类命名

3、在Choose a type:下的输入框内输入要寻找的父类,然后选择,结束。

搜索父类

package com.shiyanlou;public class Dog extends Animal {}

上面便是系统生成的代码,Dog 类继承了父类 Animal,我们 Dog 类里什么都没有写,其实它继承了父类 Animal,所以 Dog 类拥有 Animal 类的全部方法和属性(除开 private 方法和属性)。我们创建一个测试类测试一下。

class Test{    public static void main(String[] args) {        Dog a = new Dog();        a.legNum = 4;        a.bark();    }}

为什么需要继承?

如果有两个类相似,那么它们会有许多重复的代码,导致后果就是代码量大且臃肿,后期的维护性不高。通过继承就可以解决这个问题,将两段代码中相同的部分提取出来组成一个父类,实现代码的复用。

继承的特点

  • 子类拥有父类除private以外的所有属性和方法
  • 子类可以拥有自己的属性和方法
  • 子类可以重写实现父类的方法
  • Java 中的继承是单继承,一个类只有一个父类

注: Java 实现多继承的一个办法是 implements(实现)接口

2.2 方法的重写

虽然子类可以继承父类的方法,但如果子类对父类的方法不满意,想在里面加入适合自己的一些操作时,我们就需要将方法进行重写。并且子类在调用方法中,优先调用子类的方法。

比如上一个例子中 Animal 有bark()这个方法代表了动物叫,但是不同的动物有不同的叫法,比如狗是汪汪汪,猫是喵喵喵。

当然在方法重写时我们需要注意,重写的方法一定要与原父类的方法语法保持一致,比如返回值类型,参数类型及个数,和方法名都必须一致。

例如:

package com.shiyanlou;public class Dog extends Animal {       //重写父类的bark方法        public void bark() {        System.out.println("汪!汪!汪!");    }}

我们写个测试类来看看输出结果:

public class Test{    public static void main(String args[]){           Animal a = new Animal(); // Animal 对象        Dog d = new Dog();   // Dog 对象          Animal b = new Dog(); // Dog 对象,向上转型为Animal类型,具体会在后面的内容进行详解          a.bark();// 执行 Animal 类的方法         d.bark();//执行 Dog 类的方法          b.bark();//执行 Dog 类的方法       }}

运行结果:

此处输入图片的描述

我们在运行程序后,发现控制台上是不是输出了我们预想的结果呢?

2.3 继承的初始化顺序

我们学习了继承后,知道在一个继承关系中一定会有一个父类和至少一个子类,那么在程序运行的过程中,是先为父类进行初始化,还是先调用的子类进行初始化的呢?

继承的初始化顺序是先初始化父类再初始化子类。

我们根据代码来验证一下。

package com.shiyanlou;public class Animal {    public int legNum = 4; // 动物四肢的数量    //Animal的构造方法    public Animal(){        System.out.println("动物有" + legNum + "腿");        System.out.println("父类的构造方法被调用!");    }}
package com.shiyanlou;public class Dog extends Animal {    //Dog类的构造方法    public Dog(){        System.out.println("子类的构造方法被调用!");    }}
package com.shiyanlou;public class Test {    public static void main(String[] args) {        // TODO Auto-generated method stub        Dog a = new Dog(); //生成一个Dog类对象a    }}

最后输出结果:

输出结果

由此可知,系统先创建了父类对象,再创建了子类对象,先初始化了属性,再调用了构造函数。

最后再讲一个小知识。

final关键字可以修饰类、方法、属性和变量

  1. final 修饰类,则该类不允许被继承,为最终类

  2. final 修饰方法,则该方法不允许被覆盖(重写)

  3. final 修饰属性:则该类的属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值(但只能选其一)

  4. final 修饰变量,则该变量的值只能赋一次值,即变为常量

super关键字在子类内部使用,代表父类对象。

  1. 访问父类的属性 super.属性名

  2. 访问父类的方法 super.bark()

  3. 子类构造方法需要调用父类的构造方法时,在子类的构造方法体里最前面的位置:super()