抽象类(abstract)

SOBER大约 3 分钟

抽象类(abstract)

基本介绍

当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类

  1. abstract 关键字来修饰一个类时,这个类就叫抽象类: 访问修饰符 abstract 类名();
  2. abstract 关键字来修饰一个方法时,这个方法就是抽象方法访问修饰符 abstract 返回类型 方法名(参数列表): //没有方法体
  3. 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类
  4. 抽象类,是考官比较爱问的知识点,在框架和设计模式使用较多

演示

/**
 * 抽象类就是没有实现的方法
 * 所谓没有实现就是指没有方法体
 * 当一个类中存在抽象方法时,需要将该类声明为 abstract 类
 * 一般来说,抽象类会被继承,有其子类来实现抽象方法。
 * */
 abstract class EE {
    private  String name;
    public EE(String name){
        this.name = name;
    }
    public abstract void eat();
}

注意细节

  1. 抽象类不能被实例化[举例]
    public class AbstractClass {
    public static void main(String[] args) {
        // 不错 不能被实例化
        EE ee = new EE("name");
    }
    }
    abstract class EE {}
    
  2. 抽象类不一定要包含 abstract 方法。也就是说抽象类可以没有 abstract 方法 [举例]
    abstract class EE {
     // 抽象类可以没有 abstract 方法
        public void eat(){
            System.out.println("不包含 abstract 的方法");
        };
    }   
    
  3. 一旦类包含了 abstract 方法,则这个类必须声明为 abstract
  4. abstract 只能修饰类和方法,不能修饰属性和其它的。
  5. 抽象类可以有任意成员【因为抽象类还是类】,比如: 非抽象方法、构造器、静态属性等等
  6. 抽象方法不能有主体
    abstract class EE {
        public abstract void eat();
    }
    
  7. 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为 abstract 类。[举例]
    abstract class EE {
        abstract public void eat();
    }
    
    abstract class FF extends EE{};
    
    class GG extends EE {
        @Override
        public void eat() {} // 所谓实现就是有方法体
    }
    
  8. 抽象方法不能使用 privatefinalstatic 来修饰,因为这些关键字都是和重写相违背的。

练习题

  1. 思考: abstract final class A{} 能编译通过吗,why?

    错误,final是不能继承

  2. 思考: abstract public static void test20; 能编译通过吗, why?

    错误,static 关键字和方法重写无关.

  3. 思考: abstract private void test30; 能编译通过吗, why?

    错误,private 的方法不能重写

最佳实践【模板设计模式】

  1. 有多个类,完成不同的任务job

  2. 要求统计得到各自完成任务的时间

    • 使用传统方式实现
    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;
            }
        }
    }