什么是类的继承?
继承就是类和类之间的一种包含关系,具体是一种什么样的包含关系我们先来举个例子,便于我们理解。
比如:蜜蜂是昆虫,蜜蜂这个类包含在昆虫这个类之中,我们就可以描述为蜜蜂是继承昆虫,蜜蜂这个类继承了昆虫这个类,那么蜜蜂类就叫做昆虫类的子类(派生类),昆虫类就叫做蜜蜂类的父类(基类)。
很显然,在现实生活中有很多这样的例子。
需要注意的是,在Java中的继承是单继承!!一个子类只能继承一个父类,这就像我们人一样,每个人只能有一个亲爹!
2. 为什么需要继承?继承有什么好处?
提高代码的重用性
提高程序的扩展性
子类可以继承到父类的所有属性和方法
访问修饰符是用来显示属性和方法在不同的情况下是否能使用:
(图片摘自CSDN博客,博主 吴下阿吉)
3. Java继承的语法格式
Java继承的关键字:extends
格式:
class 类名(子类) extends 类名(父类) {
......
}
例如:
假设我们有一个名为 Insect(昆虫)的类,这个类包含两个属性:1)name ; 2) size ; 3)color; 两个方法:1)移动move(); 2)攻击attack()。
public class Insect {
public int size;
public String color;
public String name;
public void move() {
System.out.println("Move");
}
public void attack() {
move(); //假设昆虫在攻击前必须要先移动一次 System.out.println("Attack");
}
}
现在,你想要定义一个名为 Bee(蜜蜂)的类。Bee(蜜蜂)是Insect(昆虫)的一种,但显然,它继承了 Insect类的所有属性跟方法。
public class Bee extends Insect {
}
这里,在Bee这个类里面我们没有给出任何的属性和方法,但是其实Bee继承了Insert的所有属性跟方法。
我们再建立一个测试类Maneger
public class Manager{
public static void main(String [] args){
Bee bee = new Bee(); //实例化一个bee对象
bee.size = 10;
bee.name = "small bee";
bee.color = "yellow";
bee.move();
bee.attack();
}
}
那么最后输出的结果为:
Move
Move
Attack
4. 方法的重写什么是方法的重写?
父类中存在了这个方法,但是子类也有这个方法,而且子类方法中的具体实现和父类的不同,这个时候就可以重写父类继承的方法。方法重写的条件:
1.必须要存在继承关系。
2.子类重写父类方法时,子类方法的访问修饰符必须要大于或者等于父类方法的访问修饰符。
3.子类重写父类方法时,子类方法的返回值类型,方法名以及参数都必须要和父类的完全一致。
4.子类方法中的失信必须要和父类的不同。
例如,我们重写Bee类中的move()方法:
public class Bee extends Insect {
public void move() {
System.out.println("Fly");
}
}
那么在Manager类中,我们不做任何修改,输出的将会是:
Fly
Fly
Attack如何调用重写后的方法?
根据new关键字后的类名来决定调用谁的方法,如果new关键字后的类名是子类,那么优先调用子类的方法,如果子类没有这个方法,就会调用父类的方法;
如果new关键字后的类名是父类的,那么肯定调用父类的方法。
5.super关键字的使用
super关键字是在对象的内部使用的,它可以代表父类对象。
super关键字可以调用父类的属性和方法。那super还有什么应用呢?
(1)子类的构造过程中必须调用其父类的构造方法
这里我们可以重写一下 Insect 类和 Bee 类的构造方法:
Insect 类:
public class Insect {
public int size;
public String color;
public String name;
public void move() {
System.out.println("Move");
}
public void attack() {
move(); //假设昆虫在攻击前必须要先移动一次
System.out.println("Attack");
}
public Insect(){
System.out.println("Insect类的构造方法执行了!");
}
}Bee 类 :
public class Bee extends Insect {
public Bee(){
System.out.println("Bee类的构造方法执行了!");
}
那么在测试类中输出的结果会是:
Insect类的构造方法执行了!
Bee类的构造方法执行了!
Move
Move
Attack
产生这样结果的原因是因为我们重写了Insect 类和 Bee 类的构造方法,在测试类Manager中实例化了一个对象bee,在实例化这个对象的时候我们调用了Bee的构造方法,而子类的构造过程中必须先调用其父类的构造方法。
因为我们在定义子类的构造方法时,系统自动为我们写了父类的构造方法;
(2)如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法。
(3)如果显示的调用构造方法,必须在子类的构造方法的第一行(不是第一行编译系统会报错!)
如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参的构造方法,则编译出错。
6.类型转换自动转型
要使用自动转型必须要存在继承关系。
自动转型的格式:
格式一:
父类名 对象名 = new 子类构造方法(参数值,...);
Insect bee = new Bee();
格式二:
访问修饰符 返回值类型 方法名(父类名 参数名,...){
}
子类名 对象名 = new 子类构造方法(参数值,...);
方法名(对象名)
使用自动转型会引发什么问题?
无法调用子类中新增的属性和方法。
Java在编译时,因为编译的文件;这样在编译时只会根据对象的名的类型来进行编译,你使用
对象名调用的属性和方法如果在对象名的类型中存在,则通过编译,如果不存在则编译报错。
运行的是在内存中的对象。
Java在运行的时候,会使用对象名中存储的对象的堆内存首地址,调用方法时,会根据对象名中
存入的首地址,优先来的来调用,如果在对象中没有,才会去调用父类的。
强制转型
要使用强制转型必须要存在什么关系?
继承关系
强制转型的格式:
子类名 子类对象名 =(子类名)父类对象名;
如果要使用强制转型必须要存在什么样的情况呢?
你之前实例化对象是对应的子类对象。
7.接口什么是接口?
接口可以理解为一种特殊的类,由全局常量和公共的抽象方法所组成。
如果类是一种具体实现体,而接口定义了某一批类所需要遵守的规范,而接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法。
定义接口的关键字是:interface
接口定义的语法:
public interface 接口名 extends [接口,... ]{
//定义常量
public static final 数据类型 常量名 = 值;
//定义抽象方法
public abstract 返回值类型 方法名(数据类型 参数名,...);
}
注意:
1.因为接口就是用来被继承,被实现的,修饰符一般建 public,不能使用private和protect来修饰接口
2.接口默认会提供public、static、final、abstract关键字。
3.接口不能实例化对象。
接口的使用:
因为Java中的继承是单继承,一个类只能继承一个父类,接口就是用来丰富类的继承关系。
所以一个类可以实现一个或者多个接口。
实现接口使用的是implement关键字
继承接口的语法:
public class 类名 extends 类名 implements 接口,... {
//类必须要实现(重写)接口中所有的抽象方法。(包含接口继承父接口中的抽象方法)
}
如果要继承父类,继承父类必须要在实现接口之前。