Java中抽象类与接口的区别

作者: Arvin Chen 分类: Java 来源: Break易站(www.breakyizhan.com)

抽象: 隐藏功能的内部实现并仅向用户显示功能。即它做什么(显示),它怎么做(隐藏)。抽象类和接口都用于抽象。

抽象类与接口

1.语法层面上的区别

1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。

2.设计层面上的区别

1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

再对比一下抽象类和方法:

方法类型:接口只能有抽象方法。抽象类可以有抽象和非抽象的方法。从Java 8开始,它也可以有默认和静态方法。
最终变量:在Java接口中声明的变量默认为final。抽象类可能包含非最终变量。
变量类型:抽象类可以有最终的,非最终的,静态的和非静态的变量。接口只有静态和最终变量。
实现:抽象类可以提供接口的实现。接口不能提供抽象类的实现。
继承与抽象: Java接口可以使用关键字“implements”来实现,抽象类可以使用关键字“extends”来扩展。
多重实现:一个接口只能扩展另一个Java接口,一个抽象类可以扩展另一个Java类并实现多个Java接口。
数据成员的可访问性:默认情况下,Java接口的成员是公共的。一个Java抽象类可以拥有像private,protected等类的成员。

// Java program to illustrate the
// concept of abstract class
 
import java.io.*;
 
// abstract class
abstract class Shape 
{
    // declare fields
    String objectName = " ";
     
    Shape(String name)
    {
        this.objectName = name;
    }
     
    // declare non-abstract methods
    // it has default implementation
    public void moveTo(int x, int y)
    {
        System.out.println(this.objectName + " " + "has been moved to"
                                   + " x = " + x + " and y = " + y);
    }
     
    // abstract methods which will be
    // implemented by its subclass(es)
    abstract public double area();
    abstract public void draw();
}
 
class Rectangle extends Shape 
{
     
    int length, width;
     
    // constructor
    Rectangle(int length, int width, String name)
    {
         
        super(name);
        this.length = length;
        this.width = width;
    }
     
    @Override
    public void draw() 
    {
        System.out.println("Rectangle has been drawn "); 
    }
     
    @Override
    public double area() 
    {
        return (double)(length*width);
    }
} 
 
class Circle extends Shape
{
     
    double pi = 3.14;
    int radius;
     
    //constructor
    Circle(int radius, String name)
    {
         
        super(name);
        this.radius = radius;
    }
     
    @Override
    public void draw()
    {
         
        System.out.println("Circle has been drawn "); 
    }
     
    @Override
    public double area() 
    {
        return (double)((pi*radius*radius)/2);
    }
}
 
class GFG
{
    public static void main (String[] args) 
    {
     
        // creating the Object of Rectangle class
        // and using shape class reference.
        Shape rect = new Rectangle(2,3, "Rectangle");
        System.out.println("Area of rectangle: " + rect.area());
        rect.moveTo(1,2);
         
        System.out.println(" ");
         
        // creating the Objects of circle class
        Shape circle = new Circle(2, "Cicle");
        System.out.println("Area of circle: " + circle.area());
        circle.moveTo(2,4);
     
    }
}

输出

Area of rectangle: 6.0
Rectangle has been moved to x = 1 and y = 2
 
Area of circle: 6.28
Cicle has been moved to x = 2 and y = 4
在rectangle和circle之间没有任何通用代码,然后使用接口interface。
看到这个......
// Java program to illustrate the
// concept of interface 
import java.io.*;
 
interface Shape
{
    // abstract method
    void draw();
    double area();
}
 
class Rectangle implements Shape 
{
    int length, width;
     
    // constructor
    Rectangle(int length, int width)
    {
        this.length = length;
        this.width = width;
    }
     
    @Override
    public void draw() 
    {
        System.out.println("Rectangle has been drawn "); 
    }
     
    @Override
    public double area() 
    {
        return (double)(length*width);
    }
} 
 
class Circle implements Shape 
{
     
    double pi = 3.14;
    int radius;
     
    //constructor
    Circle(int radius)
    {
         
        this.radius = radius;
    }
     
    @Override
    public void draw() 
    {
        System.out.println("Circle has been drawn "); 
    }
     
    @Override
    public double area() 
    {
         
        return (double)((pi*radius*radius)/2);
    }
     
}
 
class GFG 
{
    public static void main (String[] args) 
    {
     
        // creating the Object of Rectangle class
        // and using shape interface reference.
        Shape rect = new Rectangle(2,3);
        System.out.println("Area of rectangle: " + rect.area());
 
        // creating the Objects of circle class
        Shape circle = new Circle(2);
        System.out.println("Area of circle: " + circle.area());
    }
}

输出

Area of rectangle: 6.0
Area of circle: 6.28

何时使用什么抽象类,接口?

如果以下任何一种语句适用于您的情况,请考虑使用抽象类:

  • 在java应用程序中,有一些相关的类需要共享一些代码行,然后你可以把这些代码行放在抽象类中,这个抽象类应该被所有这些相关的类扩展。
  • 您可以在抽象类中定义非静态或非最终字段,以便通过一种方法可以访问和修改它们所属的对象的状态。
  • 您可以期望扩展抽象类的类具有许多常用的方法或字段,或者需要除公共之外的访问修饰符(例如protected和private)。

如果以下任何一种语句适用于您的情况,请考虑使用接口:

  • 它是完全抽象的,接口中声明的所有方法必须由实现此接口的类实现。
  • 一个类可以实现多个接口。它被称为多重继承。
  • 您想要指定特定数据类型的行为,但不关心谁实现其行为。
  •   本文标题:Java中抽象类与接口的区别 - Break易站
    转载请保留页面地址:https://www.breakyizhan.com/java/3754.html

    发表笔记

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

    更多阅读