Java类的继承

继承是面向对象程序设计的一个重要特性。在现有类的基础上建立新类的处理过程称为继承。由继承而得来的类称为子类,被继承的类称为父类。直接或者间接被继承的类都是父类。子类继承父类的状态和行为,同时也可以修改父类的状态和重写父类的方法,并添加新的状态和行为。

父类与子类在这里插入图片描述

Java中的继承是通过extends关键字来实现的

class B extends A{
	...
}

B为A的直接子类,如果A又是另外某个类的子类,那么B同时也是A的间接子类。子类可以继承父类中访问权限设定为public,protected,default的成员属性和成员方法,但是不能继承访问权限为private的成员属性和成员方法,且父类的构造方法不能被继承。

方法重写

Java中的方法重写(override)是指子类重写父类的方法。子类可以改写父类方法所实现的功能,但是子类重写的方法必须与父类中对应的方法具有相同的方法名,返回值类型和参数列表。
所以说方法重写是只是方法的具体实现有所区别。
Java中的方法重写应该注意一下规则:
(1)子类重写方法的名称,返回值类型与参数列表必须与父类被重写的方法一致
(2)子类中重写方法的访问权限不能缩小,例如父类中方法权限是public,子类中只能是public;父类中方法权限是protected,子类中只能是public或者protected;父类中方法权限是默认权限,子类中只能是public或者protected或者默认权限;父类中的私有方法不能被子类继承。
(3)子类重写方法中不能抛出新的异常
方法重写使得Java支持多态,这是面向对象的三大特点(封装,继承,多态)之一

super关键字

super是当前对象里面的父对象的引用(达到可访问权限,除了private)。Java中通过super关键字来实现对父类中被重写方法的调用。
运用super可以调用父类的成员方法,构造方法和成员属性
(1)调用父类的成员方法:super.method([paramlist])
(2)调用父类的构造方法:super.([paramlist])
(3)调用父类的成员属性:super.filed

class Student {
    public int age;
    public void std(){ //声明Student类的方法std()
        age = 15;
        System.out.println("学生平均年龄为:"+age);
    }
}
 
class ThisStudent extends Student{
    public int age;
    public void std(){
        super.std();  //使用super作为父类对象的引用对象来调用父类对象里面的Std()方法
        age = 18;
        System.out.println("这个学生的年龄为:"+age);
        System.out.println(super.age);  //使用super作为父类对象的引用对象来调用父类对象中的age值
        System.out.println(age);
    }
}
 
public class TestDif {
    public static void main(String[] args) {
        ThisStudent a = new ThisStudent();
        a.std();
    }
}
/**
学生平均年龄为:15
这个学生的年龄为:18
15
18
*/

当子类调用一个由父类定义的构造方法时,super语句必须是子类构造方法中第一条被执行的语句。如果子类的构造方法中没有执行super()语句,该构造方法中还是会隐式的使用super()来调用父类中默认的构造方法,并且这条语句在子类的构造方法中都是第一个被执行。
调用父类构造方法的super关键字用法

package Liu;
class Mamal{
	public Mamal() {		//默认构造方法
		System.out.println("我是哺乳动物.");
	}
	public Mamal(int legs) {		//带参数构造方法
		System.out.println("我是一只" + legs + "的哺乳动物.");
	}
	
}
class Cat extends Mamal{
	public Cat() {
		//super();		//这一句写不写都会被执行
		System.out.println("我是一只猫.");
	}
}
class Sheep extends Mamal{
	public Sheep() {
		super(4);		//调用父类的带参数构造方法
		System.out.println("我是一只羊.");
	}
}
//测试类
public class TextSuper {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Cat cat = new Cat();
		Sheep dog = new Sheep();
	}

}
/**
我是哺乳动物.
我是一只猫.
我是一只4的哺乳动物.
我是一只羊.
*/

如果一个父类没有默认构造方法呢?那么子类不能使用父类的默认构造方法。
会报错:The constructor Mamal() is undefined

那要是在父类没有默认构造方法的情况下子类写默认构造方法呢?

class Cat extends Mamal{
	public Cat() {
		System.out.println("我是一只"+ x + "猫.");
	}
}

会报错:Implicit super constructor Mamal() is undefined. Must explicitly invoke another constructor

class Sheep extends Mamal{
	public Sheep() {
		super(4);		//调用父类的带参数构造方法
		System.out.println("我是一只羊.");
	}
}

这个不会报错,分析得:如果父类没有默认构造方法,子类在写构造方法时必须继承父类的其他带参数的构造方法,第一句要写super([paramlist]);
为了方便编程,在创建父类的时候最好写出默认构造方法,哪怕是空语句也行

public Mamal() {
		...
	}

这样给子类写构造函数的时候就不会有这么多烦恼了!
使用super调用父类中的成员方法

package Liu;
class Mamal{
	public void call() {
		System.out.println("哺乳动物会叫");
	}
}
class Sheep extends Mamal{
	public void call() {
		super.call();//调用父类的call()方法
		System.out.println("羊会咩咩叫");
	}
}
//测试类
public class TestSuper2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Sheep sheep = new Sheep();
		sheep.call();
	}

}
/**
哺乳动物会叫
羊会咩咩叫
*/

在子类中,父类中的方法需要通过super关键字进行调用,同时也可以调用父类中被子类隐藏的属性。