先举一个例子:创建Animal父类和它的子类Dog,并在子类中重写父类中的方法。
class Animal01{
public void show(){
System.out.println("父类方法");
}
}
class Dog01 extends Animal01{
@Override
public void show() {
System.out.println("子类重写了父类的方法");
}
}
既然子类无论如何都要重写父类的方法,那创建父类的方法体还有什么意思呢?对吧?所以我们可以不要父类的方法体。只声明方法就行。
这就是抽象的作用。
我们把这个方法设置为抽象方法,具体方法就是在(返回值类型/void)前面加上abstract。
记住,一个方法一旦为抽象方法那它就不能拥有方法体了,只能进行方法的声明。
public abstract void show();
}//class Animal报错
为什么会报错呢?
因为一个类中只要有一个抽象方法,那么这个类也必须为抽象方法。这里我们得到了抽象类的第一个特点。
abstract class Animal01{
public abstract void show();
}
具体做法就是在class 前面加abstract。
格式:Public abstract 返回值/void 方法名
在抽象类中既可以有抽象方法,也可以有具体方法。这是抽象方法的第二个特点。
abstract class Animal01{
public abstract void show();
public void call(){
System.out.println("动物打电话");
}
}
没有报错,证明在抽象类中既可以有抽象方法,也可以有具体方法。
抽象类可以创造对象吗?
public class Review_abstract01 {
public static void main(String[] args) {
Animal01 aa = new Animal01();
}
}
报错了。抽象类不可以创建对象。这是抽象类的第三个特点。
因此我们可以得出:
抽象类中既可以有抽象方法也可以有具体方法,如果定义了抽象方法,作用有两个:
- 不让外界创建该类的对象
- 这个类是专门让人继承用的
非抽象子类可以继承抽象父类吗?
可以,这里有两种路径。
1.既然是继承,那么子类中必然要包含抽象父类中的抽象方法(如果父类有抽象方法的话)。
因此子类也要变成抽象类。
abstract class Animal01{
public abstract void show();
public void call(){
System.out.println("动物打电话");
}
}
abstract class Dog01 extends Animal01{
}
子类Dog01变成了抽象类
2.如果一个类变成抽象类,就不能创建对象了。所以如果不想把子类变成抽象类,可以把父类的方法重写
class Dog01 extends Animal01{
@Override
public void show() {
System.out.println("重写了耶耶耶!");
}
@Override
public void call() {
System.out.println("重写了耶耶耶!!");
}
}
重写之后可以创建方法体,因此在子类中重写的子类方法就不再是抽象方法,子类也不必是抽象类。
抽象类的知识点就讲完了,我们来总结一下:
- 但凡有一个抽象方法,这个类就必须被设置为抽象类。
- 抽象类中既可以有抽象方法也可以有普通方法
- 如果定义了抽象方法,作用有两个:
1)不让外界创建该类的对象
2)这个类是专门让人继承用的
4.抽象类不能实例化
5.子类继承抽象父类,子类可以变成抽象类也可以是具体类,但是保持具体类的话要重写父类的抽象方法。
🆗,看懂了上面的内容后我们再来讲抽象类的成员特点
特点一:成员变量既可以是变量也可以是常量
abstract class Animal01{
final int num0 = 30;//常量
int num1 = 20;//变量
}
没有报错,证明成员变量既可以是变量也可以是常量
特点二:抽象类中可以有构造方法
public class Review_abstract01 {
public static void main(String[] args) {
Animal01 aaa = new Dog01();
System.out.println(aaa.num0);
System.out.println(aaa.num1);
System.out.println(aaa.num2);
}
}
abstract class Animal01{
final int num0 = 30;//常量
int num1 = 20;//变量
int num2;
public Animal01(){
num2 = 30;//我们在构造方法中给变量赋值,如果能够被输出,那就说明父类的构造方法被调用过,说明抽象类中可以有构造方法
}
}
class Dog01 extends Animal01{
public Dog01(){
System.out.println("子类的构造方法进行了");
}
}
输出结果是:
子类的构造方法进行了
30
20
30
说明,抽象类中可以有构造方法。
它的作用主要有两个:
1.让普通子类在进行实例化时可以调用构造方法
2.为了抽象类中成员的初始化。
你看懂了吗?