Java 接口中的方法是否应该使用或不使用public
访问修饰符声明?
当然,从技术上讲,这并不重要。实现 an 的类方法interface
always public
。但是什么是更好的约定呢?
Java 本身在这方面并不一致。参见例如Collection
vs.Comparable
或Future
vs. ScriptEngine
。
Java 接口中的方法是否应该使用或不使用public
访问修饰符声明?
当然,从技术上讲,这并不重要。实现 an 的类方法interface
always public
。但是什么是更好的约定呢?
Java 本身在这方面并不一致。参见例如Collection
vs.Comparable
或Future
vs. ScriptEngine
。
JLS清楚地表明了这一点:
允许但不鼓励为接口中声明的方法冗余地指定
public
和/或abstract
修饰符。
在 Java 接口中应该省略 public 修饰符(在我看来)。
由于它没有添加任何额外的信息,它只是将注意力从重要的东西上转移开。
大多数样式指南都会建议您将其排除在外,但当然,最重要的是在您的代码库中保持一致,尤其是对于每个界面。下面的例子很容易让那些不是 100% 精通 Java 的人感到困惑:
public interface Foo{
public void MakeFoo();
void PerformBar();
}
尽管这个问题很久以前就被问过了,但我觉得一个全面的描述会澄清为什么不需要在方法之前使用公共抽象,在接口的常量之前使用公共静态最终。
首先,接口用于为一组不相关的类指定通用方法,每个类都将具有唯一的实现。因此,不可能将访问修饰符指定为私有,因为它不能被其他类访问以被覆盖。
第二,虽然可以初始化接口类型的对象,但是接口是由实现它的类实现的,而不是继承的。并且由于接口可能由不在同一个包中的不同不相关类实现(实现),因此受保护的访问修饰符也无效。所以对于访问修饰符,我们只剩下公共选择了。
第三,接口没有任何数据实现,包括实例变量和方法。如果在接口中插入实现的方法或实例变量有逻辑上的原因,那么它必须是继承层次结构中的超类,而不是接口。考虑到这一事实,由于没有方法可以在接口中实现,因此接口中的所有方法都必须是抽象的。
第四,接口只能包含常量作为它的数据成员,这意味着它们必须是最终的,当然最终的常量被声明为静态的以只保留它们的一个实例。因此 static final 也是接口常量的必需品。
所以总而言之,虽然在接口的常量之前使用公共抽象和公共静态最终是有效的,但由于没有其他选项,它被认为是多余的并且不使用。
随着 Java 8/9 中接口方法的private
, static
,default
修饰符的引入,事情变得更加复杂,我倾向于认为完整的声明更具可读性(需要 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() {}
}
我会避免放置默认应用的修饰符。正如所指出的,它可能导致不一致和混乱。
我看到的最糟糕的是一个声明了方法的接口abstract
......
我使用了带有public
修饰符的声明方法,因为它使代码更具可读性,尤其是在语法高亮的情况下。不过,在我们最新的项目中,我们使用了 Checkstyle,它会public
在接口方法的修饰符的默认配置中显示警告,所以我转而省略它们。
所以我不确定什么是最好的,但我真正不喜欢的一件事是public abstract
在接口方法上使用。Eclipse 在使用“提取接口”进行重构时有时会这样做。
我不同意流行的答案,即公开意味着还有其他选择,因此不应该存在。事实是,现在有了 Java 9 及更高版本,还有其他选择。
我认为相反,Java 应该强制/要求指定“公共”。为什么?因为缺少修饰符意味着在其他任何地方都可以“打包”访问,而将其作为特殊情况会导致混淆。如果您只是简单地将其设置为带有明确消息的编译错误(例如“接口中不允许包访问。”),我们将摆脱选择省略“public”所引入的明显歧义。
注意当前的措辞:https ://docs.oracle.com/javase/specs/jls/se9/html/jls-9.html#jls-9.4
“接口主体中的方法可以声明为公共的或 私有的(第 6.6 节)。如果没有给出访问修饰符,则该方法是隐式公共的。允许但不鼓励过多地指定公共接口中方法声明的修饰符。”
看到现在允许“私人”。我认为最后一句话应该从 JLS 中删除。不幸的是,“隐式公共”行为曾经被允许,因为它现在可能会为了向后兼容而保留,并导致混淆,即没有访问修饰符意味着接口中的“公共”和其他地方的“包”。
如果没有接口并且我正在编写直接实现,我总是写我会使用的东西,即我会使用public
.
我更喜欢跳过它,我在某处读到默认情况下的接口,public
并且abstract
.
令我惊讶的是这本书 - Head First Design Patterns,正在使用public
接口声明和接口方法......这让我再次重新思考,我登上了这篇文章。
无论如何,我认为应该忽略多余的信息。
接口中的方法默认为 public 和 abstract 的原因对我来说似乎非常合乎逻辑和明显。
接口中的方法默认情况下是抽象的,强制实现类提供实现,并且默认情况下是公共的,因此实现类可以访问。
在代码中添加这些修饰符是多余且无用的,只会导致您缺乏对 Java 基础知识和/或理解的结论。
这完全是主观的。我省略了冗余public
修饰符,因为它看起来很混乱。正如其他人所提到的 - 一致性是这个决定的关键。
有趣的是,C# 语言设计者决定强制执行这一点。 在 C# 中将接口方法声明为 public 实际上是一个编译错误。 不过,跨语言的一致性可能并不重要,所以我想这与 Java 并不直接相关。
人们将通过 IDE 或 Javadoc 中的代码完成来学习您的界面,而不是通过阅读源代码。因此,在源代码中放置“公共”是没有意义的——没有人在阅读源代码。