[java特性]抽象类和接口

[toc]

abstract关键字

abstract不可与final关键字同时出现
abstract强制继承和覆写,final禁止继承和覆写
abstract不可与static关键字同时出现
abstract方法无方法体实现,static不可直接调用未实现方法
abstract不可与private关键字同时出现
abstract强制继承和覆写,private类外不可见
abstract不可与native关键字同时出现
构造方法不可声明为abstract
abstract方法由子类实现,与子类构造方法命名冲突
成员属性不可声明为abstract

抽象类

子类继承普通类时可以不覆写某一方法
抽象类必须被子类继承,抽象方法强制子类覆写
抽象类继承抽象类无需全部覆写抽象方法
抽象子类不能有与父类同名抽象方法
普通子类需要实现所有父类抽象方法
抽象类可以继承普通类

抽象类中的成员

抽象类中可以定义普通/静态成员
抽象类中的成员属性任意访问权限

抽象类中的方法

抽象类中可定义构造方法为成员赋值
抽象类中可以定义任意权限普通/静态方法
抽象方法没有方法体且有访问控制权限
抽象方法访问权限不能为private
抽象子类可覆写父抽象类方法

抽象类定义

    abstract class AbstractClassName {
        public abstract void abstractMethod (int a);   // 抽象方法
        public void simpleMethod (int a) {             // 普通方法
            this.abstractMethod (a); // 普通方法调用子类实现抽象方法
        }
 
        private int a;                                 // 普通成员
        public AbstractClassName (int a){              // 构造方法
            this.a = a;
        }
    }
 
    public class ClassName extends AbstractClassName {
        @Override
        public void abstractMethod (int a) {
            // 方法实现体
        }
    }

抽象类使用

抽象类无法被直接实例化,需要由子类实例化并向上转型
抽象类中可以没有抽象方法,但不可直接实例化

    AbstractClassName className = new ClassName();
    className.abstractMethod(3);// 调用子类实现的抽象方法
    className.simpleMethod(3);  // 调用继承父类的普通方法

抽象类隐藏子类

    public abstract class AbstractClassName {
        public static AbstractClassName getInstance() {
            return new ClassName();
        }
    }

    class ClassName extends AbstractClassName {}

接口

普通类/抽象类只能继承单个普通类/抽象类
普通类和抽象类可同时implements多个接口
接口的目的是定义标准和解耦和
接口不是类,不可继承任何一种类
接口可以同时extends多个接口
接口中一般只包含全局常量、抽象方法
普通子类强制覆写所有父接口/抽象类的所有抽象方法
抽象子类/子接口无需覆写接口中所有抽象方法
接口本身是抽象的,可省去abstract关键字

接口中的成员

接口中的成员属性只能为public static final,必须赋初值
接口中成员可简写为类型 名称 = 初值;

接口中的方法

接口中抽象方法声明为public abstract,无方法体
接口中抽象方法可简写为返回值 方法名 (参数列表);
普通/抽象子类覆写方法名称、参数、返回值与接口相同
普通子类覆写方法访问权限大于等于接口方法
接口中静态方法权限仅为public,有方法体
接口中可定义default默认方法,有方法体
接口没有构造方法

接口方法重载

同一接口中方法可重载
普通子类同时继承不同接口/抽象类情况如下

方法名称 参数列表 返回类型 子类情况
相同 相同 相同 共用同一方法
相同 不同 相同 方法正确重载
相同 相同 不同 无法通过编译

子抽象类中的抽象方法不能与父接口抽象方法重名
子接口抽象方法与父接口抽象方法重名共用同一方法

接口定义

    public interface ICustomClass {
        String str = "string";          // 全局常量
        void interfaceMethod();         // 抽象方法
    }
 
    public abstract class AbstractCustomClass {
        public void abstractMethod();   // 抽象方法
    }
 
    public CustomClassImpl [extends 父类] implements [接口1,接口2] {
        @Override
        public void interfaceMethod(){} // 实现逻辑
        @Override
        public void abstractMethod(){}  // 实现逻辑
    }

接口使用

接口只能由子类实例化向上转型

    ICustomClass cc = new CustomClass();
    cc.interfaceMethod();

接口扩充

    public interface ICustomClass {
        void methodA();
        void methodB();             // 新扩充方法
    }
 
    public class CustomClassA implements ICustomClass {
        @Override
        public void methodA() {}
        @Override
        public void methodB() {}    // 实现类扩充
    }
 
    public class CustomClassB implements ICustomClass {
        @Override
        public void methodA() {}
        @Override
        public void methodB() {}    // 实现类扩充
    }

接口增删抽象方法需要修改所有实现子类
后期修改造成大量变动问题解决方法如下

① 接口和子类之间增加抽象类

    public interface ICustomClass {
        void methodA();
        void methodB();             // 新扩充方法
    }

    public abstract class AbstractCustomClass implements ICustomClass{
        @Override
        public void methodB() {}    // 抽象类实现子类公共方法
    }

    public class CustomClassA extends AbstractCustomClass implements ICustomClass {
        @Override
        public void methodA() {
            super.methodB();        // 公共方法子实现类调用
        }
    }

    public class CustomClassB extends AbstractCustomClass implements ICustomClass {
        @Override
        public void methodA() {}
        @Override
        public void methodB() {}    // 非公共方法个性化覆写
    }

extends抽象类继承父类覆写公共方法逻辑
implements原接口强制实现所有抽象方法
此设计思想在List接口和子类设计中体现

[JDK1.8] 接口中可定义普通方法和静态方法

    public interface ICustomClass {
        public abstract void abstractMethod();  // 抽象方法
        public static void staticMethod() {}    // 静态方法逻辑
        default void plugInMethod() {}          // 扩充方法逻辑
    }

    public class CustomClass extends AbstractCustomClass {
        @Override
        public void abstractMethod() {
            ICustomClass.staticMethod();        // 静态方法
            this.plugInMethod();                // 扩充方法
        }
    }

接口解耦

接口实现类均符合接口标准设计
更改接口实现类时无需改测试类
测试类仅需关注接口标准的使用

强制类型转换

同一个子类实例的不同父类和接口之间可以强制类型转换
转型后只能调用目标类型中定义的方法

    public interface ICustomClassA { void iMethodA(); }
    public interface ICustomClassB { void iMethodB(); }
    public abstract class AbstractCustom { abstract void aMethod(); }

    public class Custom extends AbstractCustom
    implements ICustomClassA, ICustomClassB {
        @Override
        public void iMethodA() { System.out.println("iMethodA"); }
        @Override
        public void iMethodB() { System.out.println("iMethodB"); }
        @Override
        public void aMethod() { System.out.println("aMethod"); }
    }

    public class Test{
        public static void main(String[] args) {
            ICustomClassA iA = new Custom();
            ICustomClassB iB = (ICustomClassB) iA;
            AbstractCustom aC = (AbstractCustom) iB;
            iA.iMethodA();
            iB.iMethodB();
            aC.aMethod();
        }
    }
iMethodA
iMethodB
aMethod

接口实例同为Object和接口子类,可用Object接收
Object接收后强转类型可使用目标类型定义方法

    ICustomClassA iA = new Custom();
    Object obj = iA;
    if(obj instanceof ICustomClassB){
        ICustomClassB iB = (ICustomClassB) obj;
        iB.iMethodB();
    }
iMethodB

抽象类与接口对比

相同 抽象类 接口
作用 均强制子类实现abstract方法
实例化 均需子类实例化向上转型
静态成员 public static均可通过类名调用
访问权限 均不可被修饰为final
区别 抽象类 接口
内容 普通/静态成员
普通/静态/抽象/构造方法
构造块/静态块
全局常量
静态/默认/抽象方法
权限 成员非private 成员均public
关键字 abstract不可省略 abstract可省略
父类 Object 无父类
继承 单继承,可继承类和接口 多继承,只可继承接口
覆写 可覆写方法 不可覆写方法

模板方法设计模式

抽象父类规定方法的调用顺序
子类实现抽象方法的具体逻辑
调度方法设置final禁止重写

    public abstract class AbstractCriteria {
        public abstract void methodA();
        public abstract void methodB();
        public abstract void methodC();

        public final void execute() {
            this.methodA();
            this.methodB();
            this.methodC();
        }
    }

    class Criteria extends AbstractCriteria {
        @Override
        public void methodA() {}
        @Override
        public void methodB() {}
        @Override
        public void methodC() {}
    }

    class TestDemo {
        public static void main(String[] args) {
            new Criteria().execute();
        }
    }

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

©2018-2024 Howell版权所有 备案号:冀ICP备19000576号