Java中抽象类和接口的区别(abstract class VS interface)

前言:本文解决的问题

  • 什么是抽象类
  • 抽象类的应用场景
  • 接口可以有方法实现吗
  • 接口和抽象类的区别

1 什么是抽象类

在声明时含有关键字abstract就是抽象类,抽象类它可以看作具体类的一个模板,继承它的子类可以从抽象类中共享一些方法(可能是不完整的)和属性。

A class which is declared with the abstract keyword is known as an abstract class in Java. It can have abstract and non-abstract methods (method with the body). n abstract class represents an abstract concept or entity with partial or no implementation. Therefore, Abstract classes act as parent classes from which child classes are derived so that the child class will share the incomplete features of the parent class and functionality can be added to complete them.

注意事项有:

  • 抽象类不可以被实例化
  • 抽象类从本质上说还是一个类,因此可以有构造器和静态方法
  • 抽象类可以有抽象方法和非抽象方法
  • 抽象类可以有final方法,子类不可以更改

2 抽象类的使用场景

2.1 使用例子1

//定义抽象类
    public abstract class AbstractClass {
	int age;
	String gender;
	
	public AbstractClass() {//构造器
		System.out.println("I'm abstract class.");
	}	
	public void nonAbstract() {
		System.out.println("I am non abstract method in the abstract class.");
	}	
	abstract public void print();//抽象方法
}

public class AbstractClassTest extends AbstractClass {//继承了抽象类
	
	public void print() {  //实现了抽象类的方法
		System.out.println("I override from abstract class");
		}
	
	public static void main(String[] args) {
		AbstractClassTest test = new AbstractClassTest();
		test.nonAbstract();//继承自抽象类的方法
		test.print();
	}

}

结果
I'm abstract class.
I am non abstract method in the abstract class.
I override from abstract class

从上面的例子可以看到,抽象类可以有构造器,有抽象方法和非抽象方法,可以有变量。非抽象方法,子类可以直接继承;而抽象方法子类必须实现。

2.2 使用场景1

abstract class Shape{
	abstract void draw();
}

class Circle extends Shape{
	public void draw() {
		System.out.println("draw a circle.");
	}
}

class Rectangel extends Shape{
	public void draw() {
		System.out.println("draw a rectangel.");
	}
}

class Dimond extends Shape{
	public void draw() {
		System.out.println("draw a dimond.");
	}
}

public class AbstractTest2 {	

	public static void main(String[] args) {
		Shape shape = new Circle();
		shape.draw();
		
		shape = new Rectangel();
		shape.draw();
		
		shape = new Dimond();
		shape.draw();

	}

}

运行结果
draw a circle.
draw a rectangel.
draw a dimond.

可以把抽象当作模板,声明抽象类,引用任一具体的子类。

3 什么是接口

接口也是一种引用类型,定义时使用interface关键字,它时抽象方法的集合。接口可以定义final类型的变量。在jkd1.8以前,接口不能有具体方法的实现,jkd1.8后接口中可以有defaul方法体和static 方体。

An interface is an abstract type that is used to specify a contract that should be implemented by classes, which implement that interface. The interface keyword is used to define an interface and Implements keyword is used for implementing an interface by a class (in Java programming language).

4 接口实现时的注意点

4.1 接口中的default方法

为什么加入default关键字
以往当我们想在接口中新增加方法时,所有已经实现了该接口的方法都必须改写,重新实现新增的方法。为了应对这个问题,引入了default关键字。default不强制要求实现该接口的类重新实现含有default签名的方法。

例子

public interface Interface1 {
	void method1(String str);//方法签名
	
	default void log(String str){ //default 方法
		System.out.println("logging::"+str);
	}
}

public class InterfaceTest1 implements Interface1 {

	@Override
	public void method1(String str) {
		System.out.println("implement the method in interface1 "+str);
	}

	public static void main(String[] args) {
		InterfaceTest1 test = new InterfaceTest1();
		test.log("abc"); //接口中的default方法
		test.method1("abc");
	}
}

运行结果

logging::abc
implement the method in interface1 abc

分析:log方法是接口中的default方法,不强制要求实现它的子类InterfaceTest1实现该方法,但是改方法可以被继承。关于default方法的总结如下:

  • 接口中的default方法可以帮助扩展接口,而不用担心改变原来类的实现
  • default方法其实缩小了接口和抽象类的区别
  • 如果类中有与default方法具有相同给的签名,那么default方法将会被忽略,也就是调用的时类中的方法

4.2 接口中的static方法

JAVA8以后,接口中可以有static方法,但是它不能被覆盖,不能被实现它的子类中继承。

例子

    public interface Interface2 {
	default void print(String str) {
		if (!isNull(str))
			System.out.println("MyData Print::" + str);
	}
	static boolean isNull(String str) {//static 方法
		System.out.println("Interface Null Check");

		return str == null ? true : "".equals(str) ? true : false;
	}
}

public class InterfaceTest2 implements Interface2{
	
	public boolean isNull(String str) { //仅仅是简单的类方法,不是override接口里面的isNull
		System.out.println("Impl Null Check");

		return str == null ? true : false;
	}

	public static void main(String[] args) {
		InterfaceTest2 obj = new InterfaceTest2();
		obj.print("");
		obj.isNull("abc");
		
	}
}

运行结果
Interface Null Check
Impl Null Check

分析:obj.print()会调用接口中的default方法,而接口中的print方法首先会调用接口中的static方法isNull,所以输出Interface Null Check;然后执行obj.isNull("abc"),此时由于实现类中有与接口中签名一样的方法,签名中的该default方法被覆盖了,调用的是类方法中的isNull,输出Impl Null Check。如果接口中的方法isNull是default类型,那会输出什么呢?如下:
Impl Null Check
MyData Print::
Impl Null Check

关于接口中static方法总结如下:

  • 接口中的static方法是接口中的一部分,在外面不可以被使用
  • 接口中的静态方法可以用来提供一些 utinity方法,如检查非空,排序等

5 抽象类和接口的区别

5.1语法不同

  • 最容易想到的是语法不同,抽象类声明时使用的abstract class;而接口使用的是interface;
  • 继承二者时使用的关键字不同,abstract 用extends;而接口用implments;
  • 继承数量不同,JAVA中类是单继承的,一个类只能继承一个抽象类;但是可以实现多个接口;
  • 继承的方法不完全相同,子类继承抽象类,必需要实现抽象类中的方法,否则该子类也必须声明为抽象类,要不然编译出错;子类实现接口,也必须实现实现接口中的方法签名,否则编译出错。子类中没有实现接口的方法,这时可以把子类变成子接口;或者把子类变成抽象类。
  • 内部结构不同,抽象类里面可以各种变量,构造器,方法体,方法声明;接口中的变量只能是final,方法体在JAVA8后只能由static或者default修饰
  • 接口中的方法不能说是private

5.2使用场景不同

抽象类
抽象类一般用来提供一些基础通用的行为或者说方法,对于框架应用,抽象类是更好的选择。
接口
如果后期可能会更改设计,或者改的频率较高,用接口更合适,更容易扩展。


**参考阅读** https://www.javatpoint.com/abstract-class-in-java https://www.differencebetween.com/difference-between-abstract-class-and-vs-interface/ https://www.javaworld.com/article/2077421/learn-java/abstract-classes-vs-interfaces.html
原文地址:https://www.cnblogs.com/java-learner/p/9608301.html