版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18948359/article/details/84841492
简介
如果是需要了解抽象类,就需要知道什么普通类。对于普通类,可以直接产生实例化对象,并且在普通类之中可以包含有构造方法、普通方法、static 方法、常量、变量等内容。而所谓的抽象类就是指在普通类的结构中增加抽象方法的组成部分。
在所有的普通方法上都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方式是没有方法体的方法,同时抽象方法还必须使用 abstract 关键字进行定义。
拥有抽象方法的类一定属于抽象类,抽象类要使用 abstract 关键字声明。
代码实例说明
定义抽象类
使用 abstract 关键字来声明类以及方法,抽象方法是不能有方法体的。
abstract class A{ // 定义一个抽象类
public void fun() { // 普通方法
System.out.println("这是一个普通方法");
}
// 此方法没有方法声明,并且使用 abstract 关键字,表示抽象类
public abstract void print();
}
使用抽象类
由于抽象类不能直接被实例化,比如上面的例子中,使用 A a = new A()
就会报 A是抽象类,不能被实例化的错误。
原因:当一个类的实例化对象之后,就意味着这个实例化对象可以调用类中的属性和方法,但是在抽象类中存在有抽象方法,抽象方法是没有方法体,是不能被调用的,真是因为不能调用这个方法,在实例化的时候,就会报错。
对于抽象方法的使用原则如下:
- 抽象类必须有子类。即:每一个抽象类一定要被子类所继承
- 抽象类的子类(子类不是抽象类)必须要覆写抽象类之中的全部抽象方法(强制子类覆写 )
- 抽象类的对象实例化需要依靠子类完成,采用向上转型的方法处理
TestDemo.java
abstract class A{ // 定义一个抽象类
public void fun() { // 普通方法
System.out.println("A类中---这是一个普通方法");
}
// 此方法没有方法声明,并且使用 abstract 关键字,表示抽象类
public abstract void print();
}
// 一个子类只能继承一个抽象类,属于单继承局限
// B 类时抽象类的子类,并且是一个普通抽象类
class B extends A{
public void fun() {
System.out.println("B类中---这是一个普通方法 func()");
}
// 此处时候需要覆写 A 类中的抽象方法,并且是强制覆写
@Override
public void print() {
// TODO Auto-generated method stub
System.out.println("B类中---这是继承抽象类方法 print()");
}
}
public class TestDemo {
public static void main(String[] args) {
A a = new B();
a.print();
a.fun();
}
}
控制台输出
B类中---这是继承抽象类方法 print()
B类中---这是一个普通方法 func()
从上面的代码,可以总结出:
- 抽象类继承子类里面会有明确的方法覆写要求,而普通类没有
- 抽象类只是比普通类多了一些抽象方法的定义,其他组成部分与普通类完全一样
- 普通类对象可以实例化,但是抽象类的对象必须经过向上转型之后才能实例化对象使用
抽象类的相关限制
抽象类的组成和普通类的区别不大,但是在使用和定义上面会有所区别,所以以下几点也很重要
扫描二维码关注公众号,回复:
4423977 查看本文章
- 抽象类也存在构造方法。抽象类里面由于会存在一些属性,那么在抽象类中一定会存在构造方法。目的:为属性初始化。并且子类对象在实例化的时候依然满足于先执行父类构造,再执行子类构造。
- 抽象类是不能被 final 声明。因为 final 声明的类是不能有子类的,但是抽象类是必须依靠子类向上转型才能实例化对象。
- 外部抽象类不能被 static 声明,而内部的抽象类允许使用 static 声明。使用 static 声明的内部抽象类就相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称
- 抽象类中可以使用 static 关键字声明方法。
使用 static 关键字声明内部的抽象类
abstract class A{ // 定义一个抽象类
// 使用 static 关键字定义一个内部抽象类
static abstract class B{
public abstract void print();
}
}
class X extends A.B{
// 覆写 B类中的 print方法,这里是强制覆写
@Override
public void print() {
System.out.println("*********");
}
}
public class TestDemo {
public static void main(String[] args) {
// 通过内部类的方式来实现
A.B ab = new X();
ab.print(); // 输出:*********
}
}
使用 static 关键字声明抽象类中的方法
abstract class A{ // 定义一个抽象类
// 在抽象类中定义一个 static 方法
public static void print(){
System.out.println("===============");
}
}
public class TestDemo {
public static void main(String[] args) {
// 直接调用我们的抽象类中 static 方法
A.print(); // 输出:===============
}
}
特殊的设计模式
在系统类库中经常会见到以下这种设计模式。目的:为用户隐藏不需要知道的子类。
abstract class A { // 定义一个抽象类
public abstract void print(); // 抽象方法
// 定义个私有的类来继承 A
private static class B extends A {
// 根据抽象类的语法,这里需要强制覆写 A 中的 抽象方法
@Override
public void print() {
System.out.println("这个是内部子类");
}
}
// 这个方法不受实例化对象的控制
public static A getInstance(){
return new B();
}
}
public class TestDemo {
public static void main(String[] args) {
// 此时取得抽象类对象的时候,完全不需要知道 B的存在
A a = A.getInstance();
a.print();
// A.getInstance().print(); 和上面的类似
}
}
通过一个复杂的代码类理解
TestDemo.java
abstract class A{ // 定义一个抽象类
// 父类构造
public A() { // 2.由于 B 是继承于A,所以先执行A类的构造
this.print(); // 3.调用 A类中 print 方法,但是由于A 的print方法是抽象方法,所以执行子类 B类中的 print 方法
}
public abstract void print();
}
// 一个子类只能继承一个抽象类,属于单继承局限
// B 类时抽象类的子类,并且是一个普通抽象类
class B extends A{
private int num = 100;
public B(int num) { // 5.执行完成了 A类的构造方法,就轮到执行 B中的构造方法了,此时的 num的值为 30
this.num = num;
}
@Override
public void print() {
System.out.println("num="+num); // 4.由于执行当前方法的时候,并没有实例化出 B,并且由于 num 是int 类型,所以在打印的时候会打印出 int 类型的默认值为 0
}
}
public class TestDemo {
public static void main(String[] args) {
new B(30); // 1.执行构造方法
// new(30).print() // 这个时候就会输出30
}
}