Java基础笔记11-继承体系、方法重写、抽象类
1.继承简介
-
继承的作用
- 当不同的类中有大量相同的属性和方法时,此时通过继承的形式来梳理逻辑关系及简化代码。
-
关键字:extends
-
子类继承父类,那么子类就可以拥有父类中所有的公共的(public)属性及方法。
-
在继承的过程中,子类不能继承父类中的私有方法或属性,只能继承公共的。
-
代码示例:
-
class Son extends Father {} //Father类由Son类继承
-
2.super关键字
- super关键字与this关键字类似,this关键字指代的是当前的对象自身,super指代的是当前的父类对象。
- 在子类中的方法之所以可以互相调用是因为都默认持有了一个this对象,存在继承关系时,子类中在调用父类中的属性及方法时都默认持有了super关键字。
- 注意点:
- 只要存在继承关系,调用子类中的构造器时,构造方法中就会默认去执行super()。
- super()默认不写的,另外,如果要显示的写出来,那必须在第一行。
3.继承对代码执行顺序的影响
- 代码示例:
public class ExtendsDemo {
public static void main(String[] args) {
Son a = new Son();
a.show();
Son.method();
a.run();
Son.change();
}
}
class Son extends Father{
static{
System.out.println("子类static构造代码块--1");
}
{
System.out.println("子类构造代码块--2");
}
public Son() {
//super();默认不写,指代父类构造器
System.out.println("子类构造器--3");
}
public void show() {
System.out.println("子类show方法--4");
}
public static void method() {
System.out.println("子类 static method方法--5");
}
}
class Father{
static {
System.out.println("父类static构造代码块--6");
}
{
System.out.println("父类构造代码块--7");
}
public Father() {
System.out.println("父类构造器--8");
}
public void run() {
System.out.println("父类run方法--9");
}
public static void change() {
System.out.println("父类 static change方法--10");
}
}
-
输出:
父类static构造代码块--6 子类static构造代码块--1 父类构造代码块--7 父类构造器--8 子类构造代码块--2 子类构造器--3 子类show方法--4 子类 static method方法--5 父类run方法--9 父类 static change方法--10
-
由上述结果可以印证的是
- 在类的加载上,如果对象所在的类有继承关系,则在编译时先加载父类,再加载子类,由于static静态方法或属性随着类的加载而加载,所以父类静态构造代码块优先输出,之后是子类静态代码块;
- 之后创建一个子类对象,然后对象开始初始化,由于存在继承关系,优先执行super(),则父类先开始初始化:父类构造代码块,父类构造器依次初始化输出,之后子类初始化:子类构造代码块、子类构造器依次初始化输出;
- 初始化完成,调用方法,输出顺序按照调用顺序,由于存在继承关系,子类就可以拥有父类中所有的公共的(public)属性及方法,就是说子类可以正常调用父类的公共方法。
4.抽象类
-
与类的区别
- 类:描述一类具体的事物
- 抽象类:模糊的,不具体的类
-
关键词:abstract 抽象的
- 这是一个修饰符,用于告诉虚拟机该类或方法时一个抽象的类或方法。
-
抽象方法:没有方法体的方法,是不具体的,因此称之为抽象方法
-
抽象类:因为类本身是用于描述某一类具体的事物,如果该类中有抽象方法,那说明该类就是不具体的。
-
抽象方法不能使用的关键词有
- static
- 静态方法可以通过类名进行调用,因抽象方法没有方法体,调用没有意义。
- final
- 使用final修饰的方法代表最终的方法,不能被修改,但抽象方法需要被子类重写。
- private
- 经由private修饰的方法只能在本类中被调用,因抽象方法没有方法体,调用没有意义。
- static
-
抽象方法的使用:
- 抽象方法的作用只是定义某一项功能,具体的实现由子类重写来实现。
-
特点:
- 抽象类可以有抽象方法,也可以有非抽象的方法
- 抽象类中可以有构造器,但是不能创建对象,对象是由子类来创建并使用的,内存空间需要由子类对象来开辟
- 抽象类中有抽象方法,普通类没有。
5.重写
-
重写的前提:有继承或实现的关系。
-
常见于对抽象方法的重写。
-
在不同类中,方法名相同,参数列表相同,返回值类型一致,子类的的权限修饰符要大于或等于父类中的权限修饰符。
-
@Override
- 重写注解,如果有该注解,说明此方法一定是从父类中重写的,父类中的此方法删除后,编译器会在子类中报错。如果没有此注解,那么该方法就只是该类中的一个方法而已。
- 注意点:如果一个方法没有加@Override,而父类中有该方法,虚拟机仍然会认为该方法为重写的方法,父类中删除后,子类中也不会报错。
- 建议在重写方法时加上该注解。
-
什么情况下需要重写父类中的功能呢?
- 当子类有自己的特殊实现形式时,此时就可以重写父类中的功能,如果没有特殊实现就不需要重写(此时的重写不是必须的)
- 当所有的子类都有自己的特殊实现形式时,父类中的功能也就没必须有具体的实现,就会变成抽象方法,那此时,其所有的子类都必须重写父类中的全部的抽象方法
-
抽象类及重写的应用举例
public class AbstractDemo {
public static void main(String[] args) {
//定义一个新对象
Apple apple = new Apple();
Apple.type();
//引用重写方法
apple.color();
//引用父类方法
apple.taste();
}
}
/**
*抽象类及方法
*/
abstract class Fruits {
//抽象方法
abstract void color();
//抽象类中也可以有具体实现的方法
public void taste() {
System.out.println("味道好极了");
}
}
/**
*创建一个子类引用抽象父类
*/
class Apple extends Fruits{
//类型
public static void type() {
System.out.println("水晶红富士");
}
/**
* 重写color方法
*/
@Override
public void color() {
System.out.println("红色");
}
}
输出:
水晶红富士
鲜艳的红色
味道好极了
6.相关问题
- 继承可以简化代码,提高代码的利用率,那是不是只有有相同的东西就进行继承?
- 继承虽然可以简化代码,但是通常用于同一类事物,且有多个共同的属性或功能时才考虑继承
- 在Java的普通类中是不允许出现多继承的(会出现调用不明确的问题),但是可以有继承体系
- 非静态的属性及方法只有在创建对象的时候才会被加载进内存中,然后才可以通过对象进行调用,问:此处并没有创建父类的对象,为什么还能调用其中的方法?
- 只要是非静态的属性和方法想要被加载,那么一定会有对象的存在。子类在开辟空间后会在自己的空间中让出一部分用于父类使用
- 所有类对应的空间的开辟都需要通过构造器,那么父类的构造器在哪执行了,怎么执行的?
- 每个类中都有一个默认的无参构造器(类本身没有定义构造器)。