在Java中何时何地使用抽象类以及何时何地使用接口?

在Java中何时何地使用抽象类以及何时何地使用接口?,java,interface,abstract-class,Java,Interface,Abstract Class,抽象类和接口在Java中扮演着非常重要的角色,在某些情况下它们也有自己的重要性。它们具有某些特殊的特征。他们之间有一些明显的差异。让我描述其中的一些 接口和抽象类之间的主要区别之一是抽象类永远不能被实例化,而接口却可以 显然,这两个类都不能声明为final,因为它们将被其他一些非抽象类继承 它们都不能有静态方法。既不具体也不抽象(抽象静态方法实际上根本不存在) 一个接口永远不能有具体的方法(一个有实际实现的方法),但是一个抽象类也可以有具体的方法 接口不能有构造函数,但抽象类可以有构造函数

抽象类和接口在Java中扮演着非常重要的角色,在某些情况下它们也有自己的重要性。它们具有某些特殊的特征。他们之间有一些明显的差异。让我描述其中的一些


接口和抽象类之间的主要区别之一是抽象类永远不能被实例化,而接口却可以

显然,这两个类都不能声明为final,因为它们将被其他一些非抽象类继承

它们都不能有静态方法。既不具体也不抽象(抽象静态方法实际上根本不存在)

一个接口永远不能有具体的方法(一个有实际实现的方法),但是一个抽象类也可以有具体的方法

接口不能有构造函数,但抽象类可以有构造函数


这里可能会出现两个明显的问题

抽象类永远不能被实例化,因为它本质上不是一个完全实现的类,并且它的完全实现要求它被其他一些非抽象类继承。如果是这样的话,抽象类不应该有自己的构造函数,因为构造函数隐式返回自己类的对象,抽象类本身不能实例化,因此,它不应该有自己的构造函数


与抽象类相比,接口看起来更好、更适合使用,因为它施加的限制比抽象类施加的限制少。在非常特定的情况下,接口是有用的,而在非常特定的情况下,抽象类是合适的?希望黑体字会被充分考虑。

首先,你在一些地方实际上是错的:

  • 接口和抽象类之间的主要区别之一是抽象类永远不能被实例化,而接口却可以
错。抽象和接口都可以匿名实例化。
  • 显然,这两个类都不能声明为final,因为它们将被其他一些非抽象类继承
是的,虽然我个人认为没有理由接口不能是最终的,所以它们不能被扩展,但那只是我自己。我明白他们为什么做出这样的决定了。
  • 它们都不能有静态方法。既不具体也不抽象(抽象静态方法实际上根本不存在)
抽象类可以有静态方法;很抱歉
  • 一个接口永远不能有具体的方法(一个有实际实现的方法),但是一个抽象类也可以有具体的方法
是的,这是他们之间的主要区别之一。
  • 接口不能有构造函数,但抽象类可以有构造函数
是的,没错。 现在,让我们继续回答您的问题:

你的第一段没有问题。问题是什么?如果是“如果不能实例化抽象类,为什么允许它们有构造函数?”答案是这样子类就可以使用它。这里有一个例子

abstract class Parent {
    String name;
    int id;
    public Parent(String n, int i) { name = n; id = i; }
}

class Child extends Parent {
    float foo;
    public Child(String n, int i, float f) {
        super(n,i);
        foo = f;
    }
}

// later
Parent p = new Parent("bob",12); // error
Child c = new Child("bob",12); // fine!
您的第二段有一个问题,但格式不正确。我认为你只是缺少了一个“是”在那里…:)答案如下:

当您想要定义合同时,可以使用接口。下面是一个非常具体的例子:

public interface Set<E> {
    int size(); // determine size of the set
    boolean isEmpty(); // determine if the set is empty or not
    void add(E data); // add to the set
    boolean remove(E data); // remove from the set
    boolean contains(E data); // determine if set holds something
}
公共接口集{
int size();//确定集合的大小
布尔值isEmpty();//确定集合是否为空
void add(E data);//添加到集合中
布尔删除(E数据);//从集合中删除
布尔值包含(E数据);//确定集合是否包含某些内容
}
所有集合的四种常用方法

当您想要定义某些行为,但仍然拥有契约时,可以使用抽象类

public abstract class AbstractSet<E> implements Set<E> {
   // we define the implementation for isEmpty by saying it means
   // size is 0
   public boolean isEmpty() { return this.size() == 0; }
   // let all the other methods be determined by the implementer
}
公共抽象类AbstractSet实现了{
//我们定义isEmpty的实现时说
//大小为0
公共布尔值isEmpty(){返回this.size()==0;}
//让所有其他方法由实现者确定
}

大多数情况下,当讨论在决定是否应该使用接口或抽象类之间出现时,最终会给出如何使用接口或抽象类的定义,但并不总是给出为什么和何时使用接口的定义?此外,您最终可能使用的其他明显的具体类和实用程序类也并不总是被提及。实际上,在我看来,回答这个问题的正确方法是确定您正在处理的关于域或实体对象的上下文,即您的用例是什么

从一个非常高的层次上讲,Java由使用方法相互通信的对象(实体或域对象,可以在现实世界中为对象建模)组成。在任何情况下,您都希望使用接口建模行为,并在继承时使用抽象类

根据我个人的经验,我采用自上而下然后自下而上的方法。我通过查看用例和我需要的类开始寻找继承。然后我看看是否有一个超类接口类型(因为类和接口都定义了类型,为了简单起见,我将它们组合成一个词。希望它不会使它更混乱)域对象,它将包含所有对象,如在车辆的超类接口类型中,如果我正在处理子类或接口类型的用例,例如:汽车、卡车、吉普车和摩托车。如果存在层次关系,那么我定义超类接口类型和子类接口类型

正如我所说,我通常首先要做的是寻找一个合作伙伴