【八股文】一分钟掌握抽象类与接口两者之间的区别

目录

抽象类-Abstract Class

抽象类特点 

代码示例

接口-Interface

接口的特点

代码示例

接口与抽象类的区别总结

语法上的区别

语义上的区别

代码示例

执行结果


        在初中级程序员面试中这是一道很常见的面试题,这题不难但是要想有亮点还是有一定的难度。

接口和抽象类都提供了一个将接口和实现分离的结构化的方法

抽象类-Abstract Class

        在Java中被abstract关键字修饰的类称为抽象类,被abstract关键字修饰的方法称为抽象方法,抽象方法只有方法的声明,没有方法体。下面是抽象方法的语法:

abstract void method();

        如果一个类包含一个或多个抽象方法则这个类必须限定为抽象类,反过来一个抽象类中不一定包含抽象方法。

抽象类特点 

1、抽象类不能被实例化,即不能使用new关键字来实例化对象,只能被继承;

2、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法;

3、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public;

4、抽象类中的抽象方法只有方法体,没有具体实现;

5、如果一个子类实现了父类(抽象类)的所有抽象方法,那么该子类可以不必是抽象类,否则就是抽象类;

6、抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用。

代码示例

        动物都有名字,叫声以及叫;动物在叫时,输出 xxx 的叫声是:xxx;

这样我们就可以抽象一个动物类,并定一个一个模版方法speak和一个抽象方法 getCry();让不同的动物去实现这个叫声。

    /**
     * 抽象动物类,
     * 动物都有名字
     * 动物都会叫
     */
    public abstract class AbstractAnimal {

        private String name;


        /**
         * 不同的动物叫声不同,定义一个抽象方法将叫声的实现由子类实现
         *
         * @return
         */
        public abstract String getCry();

        /**
         * 动物都会叫,这是一个模版,不管什么动物的叫声输出都是一样的
         */
        public void speak() {
            System.out.println(name + "的叫声是:" + getCry());
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
}

   public class Dog extends AbstractAnimal {
        public Dog(String name) {
            super(name);
        }

        @Override
        public String getCry() {
            return "汪汪";
        }
    }

    public class Cat extends AbstractAnimal{
        public Cat(String name) {
            super(name);
        }

        @Override
        public String getCry() {
            return "喵喵";
        }
    }

接口-Interface

Java中接口使用interface关键字修饰就是接口,它是一个完全“抽象方法”的集合

接口的特点

1、接口可以包含变量、方法;变量被隐士指定为public static final,方法被隐式指定为public abstract(JDK1.8之前);

2、接口支持多继承,即一个接口可以extends多个接口,间接的解决了Java中类的单继承问题;

3、一个类可以实现多个接口;

4、JDK1.8中对接口增加了新的特性:

4.1、默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;

4.2、静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。

代码示例

 public interface Flyable {
        String A = "常量1";
        String B = "常量2";
        public static final String C = "常量3";

        void fly();

        default String getTest() {
            return "test";
        }

        static void staticMethod(){
            System.out.println("接口中静态方法");
        }

    }

接口与抽象类的区别总结

语法上的区别

抽象类 接口
实例化 不可以 不可以
构造器 支持 不支持
方法实现

抽象类可以有抽象方法也可以有具体方法实现

有抽象方法的类一定是抽象类,但是抽象类不一定是抽象类

在JDK1.8之前接口不支持具体方法实现,从1.8开始支持默认方法和静态方法
访问修饰符 抽象类可以是public, protected,default 接口只能是public
成员变量 抽象类支持普通成员变量 接口中的成员变量都是常量,即使没有使用 public static final 修饰也会被隐式的声明为常量
继承 抽象类只支持单继承 接口可以继承多个接口
main方法 抽象类可以有main 方法,可以允许 接口不可以
新增方法 抽象类新增方法必须有实现,这样可以向下兼容 JDK1.8之前接口新增方法不支持向下兼容,自1.8开始新增默认方法则可以向下兼容

语义上的区别

         这道面试题的重点在这里,主要考察的面试者的架构设计能力。

        第一点:抽象类是is-a的关系,接口是has-a的关系。我们具体举个例子来说明这个问题,有一个独角兽,我们可以抽象出一个抽象类 Animal ,我们可以说独角兽是动物;我们还可以抽象一个Flyable,因为独角兽具有飞行能力。我们是不会可以将Animal 定义为接口呢?如果设计为接口,那么可以说独角兽有动物能力吗?这样就很难理解和沟通。

        第二点:从设计模式角度来讲抽象类是模版方法模式,接口是一个约束范式。

   

代码示例

     上文说了这些区别点,是不是真的是这样呢,下面我们通过一段demo来看一下

public class InterfaceAndAbstract {


    public static class Dog extends AbstractAnimal {
        public Dog(String name) {
            super(name);
        }

        @Override
        public String getCry() {
            return "汪汪";
        }
    }

    public static class Cat extends AbstractAnimal {
        public Cat(String name) {
            super(name);
        }

        @Override
        public String getCry() {
            return "喵喵";
        }
    }

    public static class Unicorn extends AbstractAnimal implements Flyable {
        public Unicorn(String name) {
            super(name);
        }

        @Override
        public String getCry() {
            return "灰吕吕";
        }

        @Override
        public void fly() {
            System.out.println(getName() + " 飞起来了");
        }
    }

    /**
     * 抽象动物类,
     * 动物都有名字
     * 动物都会叫
     */
    public static abstract class AbstractAnimal {

        private String name;


        public AbstractAnimal(String name) {
            this.name = name;
        }

        /**
         * 不同的动物叫声不同,定义一个抽象方法将叫声的实现由子类实现
         *
         * @return
         */
        public abstract String getCry();

        /**
         * 动物都会叫
         */
        public void speak() {
            System.out.println(name + "的叫声是:" + getCry());
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        /**
         * 抽象类可以有main方法
         *
         * @param args
         */
        public static void main(String[] args) {
            Unicorn unicorn = new Unicorn("独角兽");
            unicorn.speak();

            Dog dog = new Dog("小狗");
            dog.speak();
            unicorn.fly();
            //只能通过接口调用静态方法
            Flyable.staticMethod();
        }
    }

    /**
     * 能够f
     */
    public interface Flyable {
        String A = "常量1";
        String B = "常量2";
        public static final String C = "常量3";

        void fly();

        default String getTest() {
            return "test";
        }

        static void staticMethod() {
            System.out.println("接口中静态方法");
        }

    }
}

执行结果

独角兽的叫声是:灰吕吕
小狗的叫声是:汪汪
独角兽 飞起来了
接口中静态方法

你可能感兴趣的:(Java面试题,面试,java,职场和发展)