引入Java 8时,我们可以在接口中使用默认方法。 此功能的主要驱动程序是允许扩展接口,同时保留对旧接口版本的向后兼容性。 一个示例是在现有Collection
类中引入stream()
方法。
有时,当我们想引入几种默认方法时,它们可能共享一些通用的代码库,因此,如果我们可以在接口中使用私有方法,那就太好了。 这样,我们可以重用我们的代码,还可以防止代码暴露给正在使用或正在实现接口的类。
但有一个问题。 接口中的私有和受保护的访问已推迟到Java9。那么,今天如何在Java 8中使用私有接口方法?
一个简单的解决方案
假设我们有两个方法Foo
。 bar()
和bazz()
都将返回一些难以计算的结果,这些结果是从这样的共享代码发出的:
public interface Foo {default int bar() {return complicatedMethodWithManyLinesOfCode();}default int bazz() {return complicatedMethodWithManyLinesOfCode() + 1;}// Will not work in Java 8 because interface methods cannot be private!private int complicatedMethodWithManyLinesOfCode() {// Actual code not shown...return 0;}}
通过引入一个包含私有方法的class
,我们可以从外部访问中“隐藏”该方法,并且几乎可以摆脱Java 8接口中的私有方法。 可以这样完成:
public interface Foo {default int bar() {return Hidden.complicatedMethodWithManyLinesOfCode();}default int bazz() {return Hidden.complicatedMethodWithManyLinesOfCode() + 1;}class Hidden {private static int complicatedMethodWithManyLinesOfCode() {// Actual code not shown...return 0;}}}
从外部类或接口看不到方法Foo:complicatedMethodWithManyLinesOfCode
但是可以看到Hidden
类本身。 但是,如果它们是私有的,则看不到“ Hidden
方法和字段。
此方案也可以应用于受保护的接口方法访问。 从技术上讲,我们可以在一个接口中扩展Hidden
类,该接口还可以扩展原始接口Foo
。 请记住,受保护的方法也是包可见的,因此,如果我们扩展或使用同一包中的接口,则受保护的方法也是可见的(与以往一样)。
一个缺点是隐藏方法无法访问接口中的其他方法。 通过使隐藏的静态方法采用接口类型的参数,可以轻松地解决后一个缺点。 假设complicatedMethodWithManyLinesOfCode
方法需要从Foo
接口获取另一个值,该值可以通过名为buzz()
某些接口方法获得,则它看起来可能像这样:
public interface Foo {default int bar() {return Hidden.complicatedMethodWithManyLinesOfCode(this);}default int bazz() {return Hidden.complicatedMethodWithManyLinesOfCode(this) + 1;}int buzz();class Hidden {private static int complicatedMethodWithManyLinesOfCode(Foo foo) {// Actual code not shown...return 0 + foo.buzz();}}}
翻译自: https://www.javacodegeeks.com/2016/03/java-8-declare-private-protected-methods-interfaces.html