【问题标题】:Enum class member with interface cannot find methods internally具有接口的枚举类成员在内部找不到方法
【发布时间】:2013-01-28 20:35:27
【问题描述】:

我遇到了一个奇怪的问题,我不确定这是编译器问题还是我对带有接口的枚举的理解。我正在使用 IntelliJ IDEA 12,构建一个 Android 项目,并且我有一个这样的类:

public class ClassWithEnum {
    private MyEnum myEnum;

    //Trying to access it internally here throws the error
    public boolean isActionable() {
        return myEnum.isActionable();
    }

    public enum MyEnum implements Action {
        ACTIONABLE() {
            @Override
            public boolean isActionable() { return true; }
        },
        NOT_ACTIONABLE() {
            @Override
            public boolean isActionable() { return false; }
        }
    }

    public interface Action {
        public boolean isActionable();
    }
}

现在,这最初是有效的,但现在编译器抱怨(我已经在一个全新的项目中尝试过,结果相同)并出现错误:

java: /Users/kcoppock/Documents/Projects/EnumInterfaceTest/src/com/example/EnumInterfaceTest/ClassWithEnum.java:11: cannot find symbol
symbol  : method isActionable()
location: class com.example.EnumInterfaceTest.ClassWithEnum.MyEnum

我以前做过这个(枚举由接口定义的行为),没有任何问题。有什么想法吗?

【问题讨论】:

  • 这里编译得很好。您使用的是哪个编译器和 Java 版本?
  • 这里也一样,我确实把它扔进了我的日食中......工作正常
  • @JBNizet 嗯,好吧,我在 IntelliJ 和 Java v1.6 中使用编译器(Android 项目最大)。我如何确定它使用的是什么编译器?
  • 刚看了,它说它正在使用javac

标签: java interface enums


【解决方案1】:

您需要在MyEnum 本身中实现isActionable() 方法。因为在ACIONABLENOT_ACTIONABLE 中定义的方法isActionable() 对它们来说是本地的。所以你需要 MyEnum enum 的全局方法。

改用此代码:

public enum MyEnum implements Action {
        ACTIONABLE() {
            @Override
            public boolean isActionable() { return true; }
        },
        NOT_ACTIONABLE() {
            @Override
            public boolean isActionable() { return false; }
        };
        @Override
        public boolean isActionable() { return false;}
    }

【讨论】:

  • 这似乎是合理的,这是我考虑过的,但如果枚举实际实现了接口,我认为这实际上没有必要。将编译器更改为 Eclipse 然后再改回 javac 清除了问题,并且它运行没有问题。
  • 其实我错了,只是改成Eclipse后没有重新编译。如果不添加全局覆盖,它仍然会失败。添加后,它能够按预期编译。
  • 是的。按照您的建议添加全局方法会导致编译器成功。我很好奇它是否真的是一个 javac 错误,或者只是该版本中更严格的要求。
  • javac 错误,而不是 java 错误。它在一个版本的编译器下编译和运行良好,但在另一个版本下编译和运行良好,这一事实意味着存在错误或需求更改。如果它实际上没有覆盖接口方法(因为它包含注释@Override),编译器会抱怨它实际上没有覆盖超类方法。由于它没有抱怨,我假设它实际上可以从本地对象访问。
  • 很好的答案。我要指出你也可以保持方法抽象,而不是在接口中实现它的主体:
【解决方案2】:

你可以试试这个替代方案:

   public enum MyEnum implements Action {
        ACTIONABLE(true), 
        NOT_ACTIONABLE(false);

        private final boolean actionable;

        MyEnum(boolean actionable) {
           this.actionable = actionable;
        }

        @Override
        public boolean isActionable() { 
           return this.actionable; 
        }
    }

【讨论】:

  • 这也是一个可行的解决方案。不幸的是,我使用它的真正类具有一些更复杂的功能,但仍然是很好的信息。 :)
【解决方案3】:

这看起来像一个 javac 错误。 javac 在 JDK7 中可以很好地编译它。它不在 JDK6 (javac 1.6.0_24) 中,来自 IntelliJ 和命令行。

【讨论】:

    【解决方案4】:

    似乎 1.6 的 javac 需要对接口方法进行全局覆盖,而以后的版本不需要,Eclipse 编译器也不需要。

    似乎这只是IntelliJ 的一个错误。我将编译器设置从javac 更改为Eclipse,然后改回javac,它按预期编译和运行。

    误报。 :)

    【讨论】:

    • 其实是javac的bug。即使从命令行,javac 也不会编译它。
    • @JBNizet 很有趣,所以你也可以复制它吗?不过,在更改之后,它现在可以使用 javac 编译器为我工作。让我尝试完全重新编译,看看它是否失败。
    • 是的,我可以复制它。即使 Action 接口和 Enum 被提升为顶级类,它也不会编译。
    • 看来你和@VishalK 都是正确的。如果我用 javac 重建,它会再次失败。如果我用 Eclipse 重建它会编译。如果我按照 Vishal 的建议添加默认操作,它将使用 javac 编译。
    【解决方案5】:

    有人已经回答得很完美了,我只是再补充一点:你也可以在接口中保持方法抽象:

    public enum MyEnum implements Action {
        ACTIONABLE() {
            @Override
            public boolean isActionable() { return true; }
        },
        NOT_ACTIONABLE() {
            @Override
            public boolean isActionable() { return false; }
        };
        @Override
        abstract public boolean isActionable();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      • 2010-11-09
      相关资源
      最近更新 更多