枚举实现接口、接口和方法可见性

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()

【讨论】:

以上是关于枚举实现接口、接口和方法可见性的主要内容,如果未能解决你的问题,请参考以下文章

Java中枚举值的可见性

WPF 触发器绑定:将枚举值绑定到可见性的最佳方法是啥?

Bazel Build: 规则可见性

Kotlin基础-可见修饰符嵌套类

如何限制Objective C中枚举值的可见性?

继承接口staticabstract