枚举实现接口、接口和方法可见性
Posted
技术标签:
【中文标题】枚举实现接口、接口和方法可见性【英文标题】:Enum implementing interface, interface and method visibility 【发布时间】:2014-07-11 18:22:31 【问题描述】:我刚刚遇到以下代码,这让我有点吃惊,不过我在这里将其转换为一个简单的 SSCEE:
custompackage.package1.MyEnum.java
public enum MyEnum implements MyInterface
CONSTANT_ONE()
@Override
public void myMethod()
//do something very interesting
,
CONSTANT_TWO()
@Override
public void myMethod()
//do something very interesting
;
interface MyInterface
void myMethod();
现在从这个包之外,我可以做以下事情:
Consumer<MyEnum> myMethod = MyEnum::myMethod;
但是我根本无法使用MyInterface
,我理解这是custompackage.package1
的包私有。
我不明白到底发生了什么,似乎MyEnum
添加了myMethod()
方法,但它没有实现(从外部)MyInterface
。
这是如何工作的?
【问题讨论】:
只是一个猜测,但也许接口强制MyEnum
实现myMethod()
,但是从外部来看,MyEnum
的任何用户只是看到它恰好有一个名为@987654331 的方法@,但是用户对myEnum()
正在实现的接口方法一无所知。
【参考方案1】:
正如您所说,您无法从包外部看到MyInterface
- 但MyEnum
实际上有一个公共抽象myMethod()
方法,您可以将其用作方法参考。
撇开花哨的 Java 8 新特性不谈,这是有效的(即使在包之外):
// Even MyEnum x = null; will compile, but obviously fail
MyEnum x = MyEnum.CONSTANT_ONE;
x.myMethod();
方法是从接口继承的,即使接口本身是不可见的。
这也不特定于接口和枚举。例如:
// Foo.java
package foo;
class SuperFoo
public void publicMethod()
public class Foo extends SuperFoo
// Bar.java
package bar;
import foo.Foo;
public class Bar
public void test()
Foo foo = new Foo();
foo.publicMethod();
即使Foo
甚至没有覆盖publicMethod
,也可以正常编译。就Bar
而言,它是从somewhere继承而来的,但它不知道在哪里!
【讨论】:
那么 Java 很高兴将方法添加到MyEnum
并且每个常量都有效地实现了它?
@skiwi:据我所知,它实际上并没有将它添加到字节码中 - 但它隐含地存在。
那么 Java 8 方法标记是鸭子类型的吗?
@chrylis:不,它使用继承的方式与我展示的示例相同(它可以调用publicMethod
)。【参考方案2】:
默认情况下,接口中的方法是public abstract
。字段为public static final
您可以使用该方法的原因是该接口是本地包。尝试将其公开。
【讨论】:
【参考方案3】:但是我根本无法使用 MyInterface,我理解它是 custompackage.package1 的包私有。
接口是包私有的,但所有方法(和字段)都是(隐式或显式)公共的。
似乎 MyEnum 添加了 myMethod() 方法,但它没有(从外部)实现 MyInterface。
MyEnum
有一个名为myMethod()
的公共方法,无论它是从接口继承(公共)抽象方法还是声明了方法本身。换个说法,就算外面看不到界面,外面肯定能看到MyEnum
,看到MyEnum.myMethod()
。
【讨论】:
以上是关于枚举实现接口、接口和方法可见性的主要内容,如果未能解决你的问题,请参考以下文章