【问题标题】:javac complains: cannot find symbol on enum implementing interfacejavac 抱怨:在枚举实现接口上找不到符号
【发布时间】:2010-12-03 06:40:31
【问题描述】:

我有如下定义的三种 java 类型:

Main.java:

import java.util.Arrays;
import java.util.List;

public class Main 
{
    private Object callFunction() 
    {
        OperationDefinitions func = OperationDefinitions.CONCATENATE;
        List<Object> values = Arrays.asList(new Object[] {"ABC", "-", "DEF"});
        return func.call (values);
    }

    public static void main (String[] args)
    {
        Main main = new Main(); 
        System.out.println (main.callFunction());
    }
}

Operation.java

import java.util.List;

public interface Operation
{
    abstract Object call(List<Object> params);
}

OperationDefinitions.java

import java.util.List;

enum OperationDefinitions implements Operation
{
    CONCATENATE() {
        public Object call(List<Object> params) 
        {
            StringBuilder builder = new StringBuilder();
            for (Object param : params) builder.append((String)param);
            return builder.toString();
        }
    },
    ;

}

(这几乎正是 Effective Java 2nd ed.Item 30 中给出的示例) 上面的代码在 Eclipse 中编译并运行得很好,但是使用 Sun javac 我得到以下错误:

Main.java:12: cannot find symbol
symbol  : method call(java.util.List<java.lang.Object>)
location: class OperationDefinitions
        return func.call (values);
                           ^
1 error

如果我将 Main.java 的第 12 行从 return func.call(values); 更改为 return ((Operation)func).call(values),它编译得很好。此外,如果我将三种类型(Operation、Main 和 OperationDefinitions)放在一起作为单个主类的三个子类,它也可以很好地编译。

所以我确实有解决我的问题的方法,但我想知道,为什么 javac 需要强制转换,而 eclipse 不需要?这是 javac 还是 eclipse 的 bug?

我已经尝试过 Sun javac 1.5.0_19 和 1.6.0_16

【问题讨论】:

    标签: java interface casting enums javac


    【解决方案1】:

    这是一个错误,正如“Stephen Denne”向我们展示的那样,但如果您无法更新到新版本(但应该)...只需从 OperationDefinitions 中删除接口并将方法 @ 987654322@ 在枚举中,像这样:

    public abstract Object call(List params);

    应该可以。

    【讨论】:

      【解决方案2】:

      这是Bug 6522780吗?
      还是Bug 6330385?
      或者 Bug 6724345 - 在 JDK 7 中修复 - 所以你可以测试它。

      【讨论】:

      • 看来这确实是bug 6724345。谢谢!
      【解决方案3】:

      我怀疑这实际上是javac 中的一个错误; OperationDefinitions 肯定确实 有一个(抽象)方法调用(java.util.List),因为它实现了Operation 接口。并且类定义是有效的,因为所有常量都提供了该接口的具体实现。

      可能对此负有部分责任的一件事是,据我所知,接口中定义的所有方法都必须是公共的。如果您确实在接口中使用默认访问修饰符定义了call 方法,我希望编译器会拒绝它 - 但如果没有,那么看到问题就不会让我感到惊讶。如果这是一个错字,那很好,但如果在您的代码中是这样的,请尝试将其声明为公开并查看问题是否消失。

      【讨论】:

      • 接口中的所有方法都是隐式抽象和公共的。如果您省略这些修饰符(这是 AFAIK 推荐的),编译器将为您添加它们。如果你写任何其他修饰符,你会得到错误。
      【解决方案4】:

      这可能是 Sun 的 javac 中的一个错误。 funcenum(即使 enum 实现了 Operation)并且 Enum 类没有方法 call()。为了解决这个问题,我建议更改分配:

      Operation func = OperationDefinitions.CONCATENATE;
      

      这也将说明您的期望:一个操作,而不是 enumenum 只是收集所有可能操作的便捷方式(如果您愿意,可以使用容器)。

      【讨论】:

      • 风格+1,通常这是正确的做法。这里没有说明的是,这只是真实代码的一小部分,OperationDefinitions还有额外的不在Operation中的成员函数,比如getHelp()和getDescription()
      • 更不用说我们应该总是对接口而不是类进行编程! getHelp 和 getDesctiption 应该在另一个接口中定义。让我们假设你有一个接口,比如 interface Helper {String getHelp(); String getDescription();} 所以你可以调用 getHelp() 如下: Helper helper = OperationDefinitions.CONCATENATE; helper.getHelp();
      猜你喜欢
      • 2022-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-28
      • 1970-01-01
      • 2022-12-28
      相关资源
      最近更新 更多