Java中的抽象类和接口(Abstract Class and Interface)的区别

在Java面向对象编程中,总会用到接口和抽象类,他们都是对事物的一种抽象,有一些共同点但是也有很多区别。

接口Interface

在Java中接口需要用interface关键字定义,他是对一种行为的抽象,是一种约定的协议,只定义行为不会实现具体的行为(Java 1.8中有default 方法)。

Java中定义一个接口:

public interface InterfaceName{

    public void doSomething();

}

在接口中的行为必须都是公共的,如果定义成员变量也必须是静态不可变的(static final)。接口中定义的行为都是abstract的,也可以理解为特殊的抽象。

抽象类abstract class

在面向对象的编程中,对象都是通过class来描述的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

抽象类需要用abstract关键字来定义,表示一个类为抽象类,抽象类是对一类事物共性的一种抽象,实现公共的行为,并且构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。

抽象类中用abstract表示就是个抽象类,一般都有抽象方法,如果定义没有抽象方法的抽象类,在语法层面是可行的,但是实际并很少这么用。

Java中抽象类的定义:

几点区别:

从语法定义层面看abstract class和interface

在abstract class方式中,可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface方式的实现中,只能够有静态的不能被修改的数据成员,所有的成员方法都是abstract的并且为公有的。

具体区别如下:

  • 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法(Java 1.8中有default 方法);
  • 抽象类中的成员变量可以是private、protected和public,而接口中的成员变量只能是public static final类型的;
  • 接口中不能含有静态方法和代码块,而抽象类可以有静态代码块和静态方法;
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。如果一个类实现部分接口的方法这个类也需要定义为抽象类。

从设计区分abstract class和interface

abstarct class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is a"关系,即父类和派生类在概念本质上应该是相同的。对于interface 来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。

可以理解为抽象类是对一类事物的抽象,而接口是对行为的抽象。

下面引用一个很经典的例子,大神们分析好了,我们看一看。

假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:

其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。

如果现在要求Door还要具有报警的功能。我们该如何设计类结构呢?

大家很容易想到是在Door中增加一个抽象方法alarm()。这种方法首先违反了面向对象设计中的一个单一原则,在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。如果一个门根本没有报警器功能,也得跟着修改。

另一种就是增加单独报警接口,由于Java语言不支持多重继承,所以应该把报警设计成接口。Abstract class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系,把Door设计成抽象类比较合适,报警只是一种行为从设计上说也应该设计成接口。

所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:

总结:

接口和静态类都是用于实现多态性的机制,但在语法、实现方式、成员变量、构造函数、方法实现、使用场景等方面存在一些区别。  

1. 定义关键字不同:接口使用关键字 interface 来定义,而静态类使用关键字 static class 来定义。
2. 继承或实现的关键字不同:接口使用 implements 关键字定义其具体实现,而静态类不能被继承。
3. 子类扩展的数量不同:接口的实现类可以有多个,而静态类不能被继承
4. 成员变量的不同:接口中的成员变量默认都是 public static final 的常量,而静态类中的成员变量可以是任何类型。
5. 构造函数的不同:接口中不能写构造方法,因为接口不能被实例化。但是,静态类可以有构造方法。
6. 方法实现的不同:接口中的方法默认都是公共的抽象方法,不包含具体的实现代码;而静态类中可以包含抽象方法和非抽象方法,其中抽象方法没有具体的实现,而非抽象方法有具体的实现代码。
7. 使用场景的不同:接口通常用于定义应用程序与外部设备或系统交互时所遵循的协议,而静态类通常用于定义那些不需要继承关系、不需要多态性、不需要动态创建对象的场景。

接口引申讲解:

接口声明时,如果关键字interface前面加上public->public接口,可以被任何一个类使用

如果一个接口不加public修饰-> 接口类,可以被同一个包中的类使用

java7接口中可以包含
1、常量
2、抽象方法
java8接口中额外包含:
3、默认方法
4、静态方法
java9接口额外包含:
5、私有方法

接口抽象方法:

注意:
1、接口当中的抽象方法,修饰符必须是两个固定的关键字,public abstract

2、这两个关键字修饰符,可以选择性地省略

使用:

1、接口不能直接使用。必须有一个实现类来实现接口

格式:
public  class 类名称 implements 接口名称{

    //..

}

2、接口的实现类必须覆盖重写接口中所以的抽象方法

      重写接口中的方法,访问权限一定时public

3、创建实现类的对象,进行调用

public interface MyInterface {
void method();
public default void method1(){
    System.out.println("新添加的方法");
}
 
}
public class Interface implements MyInterface {
 
    @Override
    public void method() {
    }
 
}
 
public class B {
    public static void main(String[] args) {
    Interface aa=new Interface();
    aa.method();
    aa.method1();
    }
}

接口的默认方法会被子类继承,可以由子类调用

这样就可以不用全部都重新覆盖,但子类仍然可以调用新添加的方法

注意:接口的默认方法也可以被子类覆盖重写

接口的静态方法:

public static 返回值 方法名称(参数名称){

      方法体

}

public可以省略

不能通过接口实现类的对象来调用接口当中的静态方法

通过接口名称,直接调用其中的静态方法:

接口名称.静态方法名(参数)

public interface MyInterface {
public static void method1(){
    System.out.println("调用静态方法");
}
}
 
public class B {
    public static void main(String[] args) {
    MyInterface.method1();
    }
}

接口的私有方法:

如果需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题。

但是这个共有方法不应该让实现类使用,应该是私有化的。

所以,应该把这个共有方法实设为私有的

1、普通私有方法,解决多个默认方法之间重复代码问题:

private 返回值类型 方法名称(参数列表){

    方法体}

public interface MyInterface {
    public default  void method1(){
        method();
    }
    public default void method2(){
        method();
    }
    private void method(){
        System.out.println("111");
    }
}
public class A implements MyInterface {
 
}
public class B {
    public static void main(String[] args) {
    A aa = new A();
    aa.method1();
    aa.method2();
    }
}

2、静态私有方法,解决多个静态方法之间重复代码问题:

格式:
private static 返回值 方法名称(参数列表){

方法体}

public interface MyInterface {
	public static   void method1(){
		method();
	}
	public static void method2(){
		method();
	}
	private static void method(){
		System.out.println("111");
	}
}
public class A implements MyInterface {
 
 
}
public class B{
    public static void main(String[] args) {
		MyInterface.method1();
		MyInterface.method2();
    }
}

https://blog.csdn.net/m0_52043808/article/details/123032080

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex_81D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值