实例分析Java接口和抽象类的区别,以及如何去使用它们(JDK1.8 新版本)

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

接口,在JAVA编程语言中是一个抽象类型,是抽象方法的集合,一个类通过继承接口的方式,从而来继承接口的抽象方法

 

接口

  • 接口不能被实例化
  • 接口中没有构造方法
  • 使用 implements 继承接口,支持多继承
  • 实现某个接口的类必须在类中实现该接口的全部方法
  • 接口中的变量必须是 public static final 类型的(常量)
// 此变量默认为public static final的
int count = 520;
public static final int num = 1314;
  • 接口内的方法都是抽象的(不用abstrcat声明,默认就是抽象的)
  • 接口中的抽象方法默认为 public abstract
// 抽象方法,默认为public abstract
public abstract void move();
abstract void move1();
public void move2();
void move3();
  • 接口中不能含有静态代码块和静态方法(JDK 1.8 以后,接口里可以有静态方法和方法体)
  • 所以接口中的方法体类型可以为default 和 static(默认都是public的)
default void run() { }
static void runs() { }

 接口设计的目的:对类的行为进行约束,一种行为规范

 

抽象类

  • 不能被实例化
  • 使用extends继承抽象类,支持单继承
  • 抽象类中的变量和普通类中的变量一样
  • 抽象类可以有静态代码块和静态方法
  • 如果类中有抽象方法,则必须为抽象类
  • 抽象类中可以有非抽象方法
  • 抽象方法的类型
public abstract void head();
abstract void foot();
  • 非抽象方法的类型
public void hand() { }
protected void ear(){ }
void eye() { }

抽象类设计的目的:类的模板,为了代码复用

 

实例分析

创建一个接口

// 默认为abstract
public interface Behavior {
    // 此变量默认为public static final的
    int count = 520;
    // 抽象方法,默认为public abstract
    void move();
    // 非抽象方法
    default void run() { 
        System.out.println("run");
    }
}

此接口定义了一个抽象方法 move() 和一个非抽象方法 run()

我们要记住,接口的目的是为了对类的行为进行约束,所以以后我们继承这些行为并重写接口里面的功能时,就只能用move和run这个名字,每个人的命名方式都是不同的,所以我们使用接口对代码进行了约束

创建一个抽象类

public abstract class Animal {
    // 变量与普通类中的变量一样
    String name = "robot";
    
    Animal() {
        // 构造方法
        System.out.println("抽象类构造方法");
    }
    
    // 抽象方法
    public abstract void head();

    // 非抽象方法
    public void body() {
        System.out.println("body " + name);
    }
}

此抽象类定义了一个变量、构造方法、一个抽象方法 head 和一个非抽象方法 body

在非抽象方法body中实现一些功能,这样以后我们定义类的时候,就不用每次都再去定义一些相同的功能了,只需继承这个抽象类即可,所以说设计抽象类的目的就是为了代码复用,省去了很多重复的代码

在具体的类中实现

public class Cat extends Animal implements Behavior{
    @Override
    public void head() {
        // 重写抽象类的抽象方法
        System.out.println("Override head");
    }

    @Override
    public void body() {
        // 重写抽象类的非抽象方法
        super.body();
        System.out.println("Override body");
    }

    @Override
    public void move() {
        // 重写接口的抽象方法
        System.out.println("Override move " + count);
    }

    @Override
    public void run() {
        // 重写接口中的非抽象方法
        System.out.println("Override run " + count);
    }

    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.head();
        cat.body();
        cat.move();
        cat.run();
    }
}

输出结果如下 

 

此实现类继承了 Animal 抽象类和 Behavior 接口,并重写了它们的方法

根据以上结果可以看到

  • 因为抽象类有构造方法,Cat类继承了抽象类,所以在实例化Cat类时,执行了父类的构造方法
  • 调用了head方法,因为重写了抽象的head方法,所以输出“Override head”
  • 调用了body方法,此方法是Animal抽象类中的非抽象方法,此方法本身具有输出("body " + name)的功能,因为 Cat 类继承了这个抽象类,并重写了这个非抽象方法,所以既输出原抽象方法中的内容("body" + name”),也输出重写之后的内容“Override body”
  • 调用了move方法,因为继承了接口,所以拥有接口的属性,因此可以直接使用count变量,输出 “Override move 520”
  • 最后调用了run方法,并重写run方法,输出 “Override run 520”(但不会输出原run方法中的内容,因为对接口中的非抽象方法重写时,不能使用super.run()继承父类的方法内容)

 

总之,一定要记住两者的本质区别

  • 接口设计的目的:对类的行为进行约束,一种行为规范
  • 抽象类设计的目的:类的模板,为了代码复用

 

对于抽象类和接口的理解,随着JDK版本的更新,也做出了一些改动

我在网上看到很多资料,内容大部分意思相近,但是仍有少部分不同,原因就是JDK的版本在不断更新,所以建议参考JDK原码来进行学习

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值