Javac жалуется: не удается найти символ в интерфейсе реализации enum

У меня есть три типа 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();
        }
    },
    ;

}

(Это почти точно пример, приведенный в "Эффективной Java" 2-е изд., пункт 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

Если я изменяю строку 12 Main.java от return func.call(values); до return ((Operation)func).call(values), она компилируется в порядке. Кроме того, если я помещаю три типа (Operation, Main и OperationDefinitions) вместе как три подкласса одного основного класса, он также компилируется.

Итак, у меня есть обходные пути для моей проблемы, но я задаюсь вопросом, почему javac требует приведения здесь, но eclipse нет? Является ли это ошибкой в ​​javac или в eclipse?

Я пробовал как Sun javac 1.5.0_19, так и 1.6.0_16

Ответы

Ответ 2

Это может быть ошибка в Sun javac. func является enum (даже если этот enum реализует Operation), а класс enum не имеет метода call(). Чтобы решить проблему, я предлагаю изменить назначение:

Operation func = OperationDefinitions.CONCATENATE;

Это также даст понять, чего вы ожидаете: операция, а не enum. enum - это просто удобный способ для сбора всех возможных операций (контейнер, если хотите).

Ответ 3

Это ошибка, так как "Стивен Денн" показал нам, но если вы не можете сделать обновление до новой версии (но должно)... Просто удалите inteface из OperationDefinitions и поместите метод ...call(...) в перечислении, например:

public abstract Object call(List params);

Должен работать.

Ответ 4

Я подозреваю, что это на самом деле ошибка в javac; OperationDefinitions Определенно имеет вызов (абстрактного) метода (java.util.List), поскольку он реализует интерфейс Operation. И определение класса действительно, поскольку все константы обеспечивают конкретную реализацию этого интерфейса.

Одна вещь, которая может быть частично ответственной за это, заключается в том, что, насколько мне известно, все методы, определенные в интерфейсе, должны быть общедоступными. Если вы действительно определили метод call в интерфейсе с модификатором доступа по умолчанию, я бы ожидал, что компилятор его отклонит, но если это не так, это не удивило бы меня, чтобы проблемы были проблемы. Если это была опечатка, тогда это хорошо, но если это так в вашем коде, попробуйте объявить ее общедоступной и посмотреть, не исчезла ли проблема.