抽象类(abstract)
大约 3 分钟
抽象类(abstract)
基本介绍
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类
- 用 abstract 关键字来修饰一个类时,这个类就叫抽象类: 访问修饰符 abstract 类名();
- 用 abstract 关键字来修饰一个方法时,这个方法就是抽象方法访问修饰符 abstract 返回类型 方法名(参数列表): //没有方法体
- 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类
- 抽象类,是考官比较爱问的知识点,在框架和设计模式使用较多
演示
/**
* 抽象类就是没有实现的方法
* 所谓没有实现就是指没有方法体
* 当一个类中存在抽象方法时,需要将该类声明为 abstract 类
* 一般来说,抽象类会被继承,有其子类来实现抽象方法。
* */
abstract class EE {
private String name;
public EE(String name){
this.name = name;
}
public abstract void eat();
}
注意细节
- 抽象类不能被实例化[举例]
public class AbstractClass { public static void main(String[] args) { // 不错 不能被实例化 EE ee = new EE("name"); } } abstract class EE {}
- 抽象类不一定要包含 abstract 方法。也就是说抽象类可以没有 abstract 方法 [举例]
abstract class EE { // 抽象类可以没有 abstract 方法 public void eat(){ System.out.println("不包含 abstract 的方法"); }; }
- 一旦类包含了 abstract 方法,则这个类必须声明为 abstract
- abstract 只能修饰类和方法,不能修饰属性和其它的。
- 抽象类可以有任意成员【因为抽象类还是类】,比如: 非抽象方法、构造器、静态属性等等
- 抽象方法不能有主体
abstract class EE { public abstract void eat(); }
- 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为 abstract 类。[举例]
abstract class EE { abstract public void eat(); } abstract class FF extends EE{}; class GG extends EE { @Override public void eat() {} // 所谓实现就是有方法体 }
- 抽象方法不能使用 private 、final 和 static 来修饰,因为这些关键字都是和重写相违背的。
练习题
- 思考: abstract final class A{} 能编译通过吗,why?
错误,final是不能继承
- 思考: abstract public static void test20; 能编译通过吗, why?
错误,static 关键字和方法重写无关.
- 思考: abstract private void test30; 能编译通过吗, why?
错误,private 的方法不能重写
最佳实践【模板设计模式】
有多个类,完成不同的任务job
要求统计得到各自完成任务的时间
- 使用传统方式实现
public class AbstractClass { public static void main(String[] args) { EE ee = new EE(); ee.job(); GG gg = new GG(); gg.job(); } } // 计算任务 // 1+ ...... + 8000000 class EE { public void job(){ long start = System.currentTimeMillis(); long num = 0; for (int i = 0; i < 800000000; i++) { num += i; } long end = System.currentTimeMillis(); System.out.println("EE 执行时间 " + (end - start)); } } class GG { public void job(){ long start = System.currentTimeMillis(); long num = 0; for (int i = 0; i < 800000000; i++) { num *= i; } long end = System.currentTimeMillis(); System.out.println("GG 执行时间 " + (end - start)); } }
- 使用传统方式抽离重复代码
public class AbstractClass { public static void main(String[] args) { EE ee = new EE(); ee.countTime(); GG gg = new GG(); gg.countTime(); } } class EE { public void countTime(){ /** 得到开始时间 */ long start = System.currentTimeMillis(); job(); /** 得到结束时间 */ long end = System.currentTimeMillis(); System.out.println("EE 执行时间 " + (end - start)); } public void job(){ long num = 0; for (int i = 0; i < 800000000; i++) { num += i; } } } class GG { public void countTime(){ long start = System.currentTimeMillis(); job(); long end = System.currentTimeMillis(); System.out.println("GG 执行时间 " + (end - start)); } public void job(){ long num = 0; for (int i = 0; i < 800000000; i++) { num *= i; } } }
- 使用模板设计模式
/** Template 父类中 */ abstract public class Template { public abstract void job();// 抽象方法 public void countTime() { // 实现的方法 /** 得到开始时间 */ long start = System.currentTimeMillis(); job(); /** 得到结束时间 */ long end = System.currentTimeMillis(); System.out.println("任务执行时间 " + (end - start)); } } /** RR 子类中 */ public class RR extends Template{ @Override public void job() { long num = 0; for (int i = 0; i < 800000000; i++) { num += i; } } } /** TT 子类中 */ public class TT extends Template{ @Override public void job() { long num = 0; for (int i = 0; i < 800000000; i++) { num *= i; } } }