Java 接口中的方法是不是应该使用或不使用公共访问修饰符来声明?

Posted

技术标签:

【中文标题】Java 接口中的方法是不是应该使用或不使用公共访问修饰符来声明?【英文标题】:Should methods in a Java interface be declared with or without a public access modifier?Java 接口中的方法是否应该使用或不使用公共访问修饰符来声明? 【发布时间】:2010-09-14 18:25:36 【问题描述】:

Java 接口中的方法是否应该使用public 访问修饰符声明?

当然,从技术上讲,这并不重要。实现interface 的类方法始终为public。但是什么是更好的约定呢?

Java 本身在这方面并不一致。参见例如CollectionComparable,或FutureScriptEngine

【问题讨论】:

这很糟糕,因为将其写为公开意味着它可以是非公开的 你应该避免任何形式的冗余语法。 @Pacerier,虽然我同意在这种情况下使用 public 是不好的,但默认接口方法 可以 现在(使用 java 9)是私有的。我建议你删除你的评论,因为它已经过时了。 是的,Java 9 中的情况可能会发生变化。“将其写为公开意味着它可以非公开”。由于 that 在 Java 9 中似乎是可能的,所以这个论点现在有利于写出 public 【参考方案1】:

JLS 说明了这一点:

允许但不鼓励为接口中声明的方法重复指定 public 和/或 abstract 修饰符。

【讨论】:

上面的 JLS 链接在我阅读它时适用于 Java 7。在关于 Java 9 允许非公共方法的 cmets 之后,我只是想确认 SE9 JLS 仍然存在非常相似的措辞。 (public 部分相同,and/or abstract 部分已删除) 在SE11 JLS中仍然如此 更新:Java 13 docs.oracle.com/javase/specs/jls/se13/html/jls-9.html#jls-9.4【参考方案2】:

在 Java 接口中应该省略 public 修饰符(在我看来)。

由于它没有添加任何额外的信息,它只是将注意力从重要的东西上转移开。

大多数样式指南都会建议您将其省略,但当然,最重要的是在您的代码库中保持一致,尤其是对于每个界面。下面的例子很容易让那些不是 100% 精通 Java 的人感到困惑:

public interface Foo
  public void MakeFoo();
  void PerformBar();

【讨论】:

你有这样的风格指南的链接吗? 一致性是迄今为止最重要的事情,是这类问题 99% 的答案。 同意重新:一致性。适合您的编码标准文档的东西:) Bno:一个例子是 Java 语言规范,另一个例子是 Checkstyle。【参考方案3】:

尽管这个问题很久以前就被问过了,但我觉得一个全面的描述会澄清为什么不需要在方法之前使用公共抽象,在接口的常量之前使用公共静态最终。

首先,接口用于为一组不相关的类指定通用方法,每个类都有一个唯一的实现。因此不能将访问修饰符指定为私有,因为它不能被其他类访问以被覆盖。

第二,虽然可以初始化接口类型的对象,但是接口是由实现它的类实现的,而不是继承的。并且由于接口可能由不在同一个包中的不同不相关类实现(实现),因此受保护的访问修饰符也无效。所以对于访问修饰符,我们只剩下公共选择了。

第三,接口没有任何数据实现,包括实例变量和方法。如果在接口中插入实现的方法或实例变量有逻辑上的原因,那么它必须是继承层次结构中的超类,而不是接口。考虑到这个事实,由于没有方法可以在接口中实现,因此接口中的所有方法都必须是抽象的。

第四,接口只能包含常量作为其数据成员,这意味着它们必须是最终的,当然最终的常量被声明为静态的以仅保留它们的一个实例。因此 static final 也是接口常量的必需品。

因此,总而言之,尽管在接口的常量之前使用 public abstract 和在接口的常量之前使用 public static final 是有效的,但是由于没有其他选项,因此它被认为是多余的并且不被使用。

【讨论】:

【参考方案4】:

随着在 Java 8/9 中为接口方法引入 privatestaticdefault 修饰符,事情变得更加复杂,我倾向于认为完整的声明更具可读性(需要 Java 9 编译) :

public interface MyInterface 

    //minimal
    int CONST00 = 0;
    void method00();
    static void method01() 
    default void method02() 
    private static void method03() 
    private void method04() 

    //full
    public static final int CONST10 = 0;
    public abstract void method10();
    public static void method11() 
    public default void method12() 
    private static void method13() 
    private void method14() 


【讨论】:

如何在一行中添加默认的方法并指定默认的访问修饰符default default void myDefaultMethod() 抛出错误。【参考方案5】:

我会避免放置默认应用的修饰符。正如所指出的,它可能导致不一致和混乱。

我看到的最糟糕的是一个接口声明了abstract...

【讨论】:

【参考方案6】:

我使用带有public 修饰符的声明方法,因为它使代码更具可读性,尤其是语法高亮。不过,在我们最新的项目中,我们使用了 Checkstyle,它在接口方法上使用 public 修饰符的默认配置显示警告,所以我转而省略它们。

所以我不太确定什么是最好的,但我真正不喜欢的一件事是在接口方法上使用public abstract。 Eclipse 在使用“Extract Interface”进行重构时有时会这样做。

【讨论】:

但只有当你选中这两个复选框时,才能将方法声明为 public、abstract。【参考方案7】:

我不同意流行的答案,即公开意味着还有其他选择,因此不应该存在。事实上,现在有了 Java 9 及更高版本,还有其他选择。

我认为 Java 应该强制/要求指定“公共”。为什么?因为缺少修饰符意味着在其他任何地方都可以“打包”访问,而将其作为特殊情况会导致混乱。如果您只是简单地将其设置为带有明确消息的编译错误(例如“接口中不允许包访问。”),我们将摆脱选择省略“public”所引入的明显歧义。

注意当前的措辞:https://docs.oracle.com/javase/specs/jls/se9/html/jls-9.html#jls-9.4

"接口主体中的方法可以声明为 public私人(§6.6)。如果没有给出访问修饰符,则该方法是隐式公共的。这是允许的,但不鼓励这样做 样式,为方法冗余指定公共修饰符 接口中的声明。”

看到现在允许“私人”。我认为最后一句话应该从 JLS 中删除。不幸的是,“隐式公共”行为曾经被允许,因为它现在可能会为了向后兼容而保留,并导致混淆,即没有访问修饰符意味着接口中的“公共”和其他地方的“包”。

【讨论】:

【参考方案8】:

如果没有接口并且我正在编写直接实现,我总是写我会使用的东西,即我会使用public

【讨论】:

你还要显式声明所有接口方法抽象吗? 它是一个接口,而不是一个抽象类。至于'public',你想起来的时候已经打了7个字符,很重要!这也是它在实现中的定义方式,+1 表示一致性,而 -1 表示冗余。【参考方案9】:

接口中的方法默认为 public 和 abstract 的原因对我来说似乎非常合乎逻辑和明显。

接口中的方法默认是抽象的,强制实现类提供实现,默认情况下是公共的,因此实现类可以访问。

在代码中添加这些修饰符是多余且无用的,只会导致您缺乏对 Java 基础知识和/或理解的结论。

【讨论】:

但是您也可以在抽象类中实现具有受保护访问权限的抽象方法。所以公开不是必需品。添加与默认值相同的显式内容总是多余的,但并不总是无用的。 但问题是关于接口的。我不想离题。我的意思是,从 Java 8 开始,我们也可以在接口中讨论私有和默认方法,对吧?因此,如果我们愿意,这个讨论可以进行很长时间。 ;)【参考方案10】:

我更喜欢跳过它,我在某处读到默认接口是publicabstract

令我惊讶的是,这本书 - Head First Design Patterns,正在使用 public 与接口声明和接口方法......这让我再次重新思考,我登上了这篇文章。

无论如何,我认为应该忽略多余的信息。

【讨论】:

澄清一下,如果您在接口声明中省略了public 访问修饰符,那么默认情况下它不会是公开的和抽象的。 docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html【参考方案11】:

这完全是主观的。我省略了多余的public 修饰符,因为它看起来很混乱。正如其他人所提到的 - 一致性是这个决定的关键。

有趣的是,C# 语言设计者决定强制执行此操作。 在 C# 中将接口方法声明为 public 实际上是一个编译错误。尽管跨语言的一致性可能并不重要,所以我想这与 Java 并不直接相关。

【讨论】:

【参考方案12】:

人们将通过 IDE 或 Javadoc 中的代码完成来学习您的界面,而不是通过阅读源代码。因此,在源代码中添加“公共”是没有意义的——没有人在阅读源代码。

【讨论】:

我真的不同意没有人阅读源代码的说法。我认为很多人使用例如 Eclipse 中的 F3 来放大代码。 Maven 等工具提供了下载源代码的选项,而不仅仅是 JavaDoc,这是有原因的。 这不是不向接口添加public 访问修饰符的确切原因。这是经过精心设计并经过深思熟虑的。

以上是关于Java 接口中的方法是不是应该使用或不使用公共访问修饰符来声明?的主要内容,如果未能解决你的问题,请参考以下文章

Java单元测试对私有方法测试

Java单元测试对私有方法测试

OCUnit的测试用例类中是不是需要在公共接口中定义测试方法

Java2C#翻译:C#接口中的公共方法

为啥我们应该将接口方法声明为公共的? [复制]

包装或不包装:在服务外观中包装数据访问