我什么时候应该在 Java 中使用接口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2586389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:32:39  来源:igfitidea点击:

When should I use an interface in java?

javainterface

提问by Julio

A good example of when exactly to use interfaces specifically in Java would be ideal and any specific rulings that apply.

什么时候在 Java 中专门使用接口的一个很好的例子是理想的,任何适用的特定规则都是理想的。

采纳答案by BalusC

Use interfaces to define an application programming contract (blueprint, interface) which "3rd-party" vendors have to fully adhere and implement. This way the endusers can just code against the API contract and easily switch of the concrete implementation "under the hoods" without changing the code.

使用接口来定义“3rd-party”供应商必须完全遵守和实施的应用程序编程合同(蓝图、接口)。通过这种方式,最终用户只需根据 API 合同进行编码,即可轻松切换“幕后”的具体实现,而无需更改代码。

The JDBC APIis an excellent example. It exist of almost only interfaces. The concrete implementations are provided as "JDBC drivers". This enables you to write all the JDBC code independent of the database (DB) vendor. You can just change the JDBC driver without changing any line of Java code (except of any hardcoded DB-specific SQL code) whenever you'd like to switch of DB vendor.

JDBC API是一个很好的例子。它几乎只有接口存在。具体实现作为“JDBC 驱动程序”提供。这使您能够独立于数据库 (DB) 供应商编写所有 JDBC 代码。只要您想切换 DB 供应商,您就可以只更改 JDBC 驱动程序,而无需更改任何 Java 代码行(任何硬编码的特定于 DB 的 SQL 代码除外)。

Another example is the Java EE API, it also contains pretty much interfaces and abstract classes. The concrete implementations are provided as "Java EE application servers", "Servletcontainers", etc, such as Sun Glassfish, Apache Tomcat, etc. This enables you to deploy the webapplication (WAR) to whatever Java web server you like.

另一个例子是Java EE API,它也包含相当多的接口和抽象类。具体实现以“Java EE 应用服务器”、“Servletcontainers”等形式提供,例如 Sun Glassfish、Apache Tomcat 等。这使您可以将 Web 应用程序 (WAR) 部署到您喜欢的任何 Java Web 服务器。

回答by Julio

Interfaces are used when you need multiple implementations of the same behavior. Here is an example of an interface that objects could implement to show that they all can be serialized to XML.

当您需要相同行为的多个实现时,将使用接口。下面是一个对象可以实现的接口示例,以表明它们都可以序列化为 XML。

public interface Xmlizable
{
    public String toXML();
}

then you can just pass around "Xmlizable" interfaces into methods that only care about that one interface.

那么您可以将“Xmlizable”接口传递给只关心该接口的方法。

回答by coolest_head

A good place to look at would be the collections framework.

一个值得关注的好地方是集合框架。

java.util.List //interface

java.util.ArrayList //Concrete class
java.util.LinkedList //Concrete class

So you can write code like this:

所以你可以写这样的代码:

List l = new ArrayList();

l.add(..)
//do something else.

If in future you want to change the implementation with say LinkedListor you own AwesomeList which implements Listinterface, all you have to do is change the very first line to:

如果将来您想使用 sayLinkedList或您自己的AwesomeList which implements List接口更改实现,您所要做的就是将第一行更改为:

List l = new MyAwesomeList();
or
List l = new LinkedList();

The rest of the code would follow through.

其余的代码将跟进。

回答by Kannan Ekanath

Have a look at JDK collection tutorial at link text. Think about Collections. What comes to your mind? It could be ordered or it may not be ordered and it may have duplicates or not.

链接文本中查看 JDK 集合教程。想想收藏。你想到了什么?它可以被订购,也可以不被订购,它可能有重复或不重复。

So Collection is an interface with List (ordered) and Set (unordered) as sub interfaces. Now there are many questions with Lists, should it be synchronised/or not, should it be a linked list or not etc. Each "behaviour" will have its own interfaces/abstract classes.

所以Collection是一个以List(有序)和Set(无序)为子接口的接口。现在有很多关于列表的问题,它应该同步/还是不同步,它是否是一个链表等等。每个“行为”都有自己的接口/抽象类。

Abstract classes are needed when you want to specify "some" behaviour in collections. For example all collections (sets/lists etc) can have a "toString" representation which is just iterate over the elements (ordered/or not) and stringify them. That behaviour can be present in "AbstractCollection" etc.

当您想在集合中指定“某些”行为时,需要抽象类。例如,所有集合(集合/列表等)都可以有一个“toString”表示,它只是迭代元素(有序/或无序)并将它们字符串化。该行为可以出现在“AbstractCollection”等中。

If you follow the hierarchy of JDK collections, it is an excellent place to learn about interfaces and abstract classes :)

如果您遵循 JDK 集合的层次结构,这是了解接口和抽象类的绝佳场所:)

回答by Boris Pavlovi?

Try to understand Strategy Design Pattern

尝试理解策略设计模式

回答by gustafc

Basically, you can choose between interfaces and abstract classes when you need to "leave out" some implementation details. The interface is usually the better choice, as client classes can implement any amount of interfaces, but they can only one have one superclass ("inheritance is a scarce resource", as they put it).

基本上,当您需要“省略”一些实现细节时,您可以在接口和抽象类之间进行选择。接口通常是更好的选择,因为客户端类可以实现任意数量的接口,但它们只能有一个超类(“继承是一种稀缺资源”,正如他们所说的那样)。

Why would you want either an abstract class or an interface? Because sometimes, when you write an algorithm you don't care howa specific sub-step of it is done, just that it is doneaccording to some kind of contract. An example would be the Collections API, with Listbeing an interface - usually, when you use a List, you don't really care if it's saving stuff in an array, or in a linked list of nodes, or in some other kind of way. As long as it stores the stuff you put in it in the order you put them there, you're happy.

为什么要抽象类或接口?因为有时,当您编写算法时,您并不关心的特定子步骤是如何完成的,只关心它是根据某种契约完成的。一个例子是 Collections API,其中List是一个接口——通常,当你使用 a 时List,你并不真正关心它是在数组中保存东西,还是在节点的链接列表中,或者以某种其他方式. 只要它按照您放置的顺序存储您放入其中的东西,您就很高兴。

Then we have AbstractList: An abstract class implementing List, which provides implementation of almost everything a fully-fledged Listneeds - to create your own Listimplementation, all you have to do is extend AbstractListand fill in a few methods. This is a prime example of when an abstract class is a good choice - when you want to provide an almost-complete implementation of something, which only is lacking a few gaps which needs to be filled in by the client code.

然后我们有AbstractList: 一个抽象类实现List,它提供了一个成熟List需要的几乎所有东西的实现- 要创建你自己的List实现,你所要做的就是扩展AbstractList和填充一些方法。这是抽象类什么时候是一个不错的选择的一个主要例子——当你想提供一个几乎完整的东西的实现时,它只缺少一些需要由客户端代码填补的空白。

Hint:If you make an abstract class containing only abstract methods, you should probably make an interface of it.

提示:如果你创建一个只包含抽象方法的抽象类,你可能应该为它创建一个接口。

回答by Searles

Use interfaces whenever you plan to replace an implementation class by another class at some point of development.

每当您计划在某个开发点用另一个类替换一个实现类时,请使用接口。

I also would recommend to use interface backends for all classes in inheritance relationships at least in more serious projects: Unfortunately I don't have the link anymore but a developer of the language Java once said, that including Class-Inheritance was the biggest mistake in designing the language.

我还建议至少在更严重的项目中为继承关系中的所有类使用接口后端:不幸的是,我不再有链接,但是 Java 语言的开发人员曾经说过,包括类继承是最大的错误设计语言。

The arguments are quite good: Using proper design, it is always possible to replace class inheritance by interface inheritance and you gain a lot concerning code maintainance. It is also easier to preserve natural type relations (like e.g. from geometry ("a square is a rectangle"-stuff) than with class inheritance.

论点非常好:使用适当的设计,总是可以用接口继承代替类继承,并且您可以获得很多关于代码维护的信息。与类继承相比,保留自然类型关系(例如来自几何(“正方形是矩形”))也更容易。

回答by Zoltán Ujhelyi

A basic principle of OOP is information hiding: hide the implementation details, and show only a description of the basic services to the caller.

OOP 的一个基本原则是信息隐藏:隐藏实现细节,只向调用者展示基本服务的描述。

Java has to constructs for this goal: interfaces and abstract classes. You can define an interface, and write your code, that it only depends on the interface by calling the "available methods" defined in it.

Java 必须为这个目标构建:接口和抽象类。您可以定义一个接口并编写您的代码,它仅通过调用其中定义的“可用方法”来依赖于该接口。

Information hiding is usable both for reading external classes (external in a sense that it comes outside the module you are writing) - this way you can define what methods you need, and there is no need to infer its concrete implementation type - , or when defining a data type usable outside your classes - a typical example for this is e.g. the Collection API or J2EE, as other already mentioned.

信息隐藏可用于读取外部类(从某种意义上说是外部类,它位于您正在编写的模块之外) - 这样您就可以定义所需的方法,而无需推断其具体实现类型 - 或何时定义一个可以在你的类之外使用的数据类型 - 一个典型的例子是例如 Collection API 或 J2EE,正如其他已经提到的。

Both interfaces and abstract classes provide these details - but there are two major differences: interfaces support multiple inheritance, while abstract classes can hold a base implementation. To maximize their efficiency, when defining an interface, you should also define an abstract class with a meaningful default implementation. If the user of the interface does not need to extend any other class, it can extend this abstract class, otherwise it needs to implement all methods from the interface. On the other hand make sure not to read this abstract class directly, the interface should be enough as abstraction.

接口和抽象类都提供了这些细节——但有两个主要区别:接口支持多重继承,而抽象类可以包含基本实现。为了最大化它们的效率,在定义接口时,您还应该定义一个具有有意义的默认实现的抽象类。如果接口的用户不需要扩展任何其他类,则可以扩展这个抽象类,否则需要实现接口中的所有方法。另一方面确保不要直接读取这个抽象类,接口应该足够抽象。

回答by bakkal

Interfaces in Remote communication:

远程通信接口:

Interfaces can also be used to define an agreed upon "protocol" for communicating between different portions of the system, possibly through remote calls. So the interface only defines what can be called, with what parameters, and what will be returned after the call. The client usesthe interface and the server implementsthe concrete actual code for example.

接口也可以用来定义一个商定的“协议”,用于在系统的不同部分之间进行通信,可能是通过远程调用。所以接口只定义了可以调用什么,带什么参数,调用后返回什么。例如,客户端使用接口,服务器实现具体的实际代码。

Side Note:

边注:

In Java you can only inherent (extend) from one class, but you can implement more than one interface, so sometimes you will have to use interfaces when you need that sort of multiple inheritance and when you decide not to use composition over inheritance.

在 Java 中,您只能从一个类继承(扩展),但您可以实现多个接口,因此有时当您需要这种多重继承以及决定不使用组合而不是继承时,您将不得不使用接口。

回答by Esko

This answer is essentially the same as coolest_head's, just a bit more explicit in conveying the usefulness.

这个答案与coolest_head 的答案基本相同,只是在传达有用性方面更明确一点。

As coolest_head explains, interfaces are useful when you may want to switch around the possible subcomponents of your program in the future. They also allow you to separate concerns of various parts of your program's structure more easily since with interfaces you can ensure that certain non-related classes etc. just aren't visible to other parts of the program.

正如coolest_head 解释的那样,当您将来可能想要切换程序的可能子组件时,接口很有用。它们还允许您更轻松地分离程序结构各个部分的关注点,因为使用接口可以确保某些不相关的类等对程序的其他部分不可见。

As an example, lets assume that you want to read arbitrary data and print it, like so:

例如,假设您要读取任意数据并打印它,如下所示:

SomeReader someReader = new SomeReader();
String data = someReader.readLine();
System.out.println(data);

Nothing fancy here, right? But, while this example is simple, it's already tied to the SomeReaderclass which means that all the changes you make to that class must be propagatedto the class where you're using the class - especially if you refactor some inner parts! Instead, you want to do this

这里没什么好看的,对吧?但是,虽然这个示例很简单,但它已经与SomeReader类相关联,这意味着您对该类所做的所有更改都必须传播到您使用该类的类 - 特别是如果您重构了一些内部部分!相反,你想这样做

IMyReader reader = new SomeReader();
System.out.println(reader.readLine());

You're almost there - now the printing code doesn't care about the specific implementation anymore, only about the parts which are exposed by the interface. This is usually enough because now you can just switch around that one newstatement and you get new implementations and whatever which still work as expected (as long as the interface's contract is respected among the implementing classes!). This is especially handy when you end up using that one specific object multiple times - here I'm using it just once but really, if you're working with for example lists, how many operations you usually do the same list?

你就快到了——现在打印代码不再关心具体的实现,只关心接口公开的部分。这通常就足够了,因为现在您只需切换该new语句即可获得新的实现以及仍然按预期工作的任何内容(只要在实现类中尊重接口的约定!)。当您最终多次使用该特定对象时,这特别方便 - 在这里我只使用一次,但实际上,如果您正在使用例如列表,那么您通常会对同一个列表执行多少操作?

So, to really blow this example out of proportions, here's what your code may end up looking like

所以,为了真正让这个例子不成比例,这就是你的代码最终可能看起来像

public class RowPrinter {

    private final IMyReader reader;

    public RowPrinter(IMyReader reader) {
        this.reader = reader;
    }

    public void print() {
        IMyReader reader = getReader();
        System.out.println(reader.readLine());
    }

    protected IMyReader getReader() {
        return reader;
    }
}

Notice that part with the constructor? That's inversion of controland let me just tell you, that's a cool piece of software engineering right there. I can speak from experience it helps you with a lot of hassle, whether it's switching from database product to another or making certain parts of code thread safe. Or maybe you just want to add a layer of logging to some class, easily doable with a wrapping decoratorwhich happens to implement the same interface as the wrapped class. And this is just the beginning.

注意到构造函数的那部分了吗?这是控制反转,让我告诉你,这是一个很酷的软件工程。我可以从经验中讲,它可以帮助您解决很多麻烦,无论是从数据库产品切换到另一个产品还是使代码的某些部分线程安全。或者,您可能只想向某个类添加一个日志记录层,使用包装装饰器很容易实现,该装饰器恰好实现了与包装类相同的接口。而这仅仅是个开始。

Interfaces bring lots of benefits which usually aren't that obvious from simple examples although the simple examples do get you going properly. While interfaces in Java are a language construct, they're actually more of a programming paradigm than just a feature of a single language, in some languages emulating interfaces truly is beneficial if you figure out the correct way to do it.

接口带来了很多好处,虽然简单的例子确实可以让你正确地进行,但从简单的例子中通常不会那么明显。虽然 Java 中的接口是一种语言构造,但它们实际上更像是一种编程范式,而不仅仅是一种语言的特性,在某些语言中,如果您想出正确的方法来模拟接口,那么它确实是有益的。