2009-02-24 4 views
10

Синтаксический сахар, предоставляемый средством Java enum, может иногда быть немного запутанным. Рассмотрим следующий пример, который не компилируется:Статический контекст в определении перечисления

public enum TestEnum { 

    FOO("foo") { 
     public void foo() { 
      helper(); // <- compiler error 
     } 
    }; 

    String name; 
    TestEnum(String name) { 
     this.name = name; 
    } 

    public abstract void foo(); 

    private void helper(){ 
     // do stuff (using this.name, so must not be static) 
    } 
} 

Может кто-нибудь объяснить, почему компилятор говорит

Non-статический метод «помощник()» не может ссылаться из статического контекста

Как именно этот контекст статичен?

Вы можете сделать это компиляции путем изменения вызова this.helper() (здесь один запутанным пункт: если мы на самом деле в «статическом контексте», как предполагает компилятор, как может «this» работать) или по увеличивая видимость helper() до уровня по умолчанию. Что бы вы предпочли? Кроме того, не стесняйтесь предлагать лучшее название вопроса :-)

Редактировать: Я нашел some discussion about this - но реальных ответов нет. Мой коллега считает, что работа this.helper() на самом деле является ошибкой компилятора. И действительно, с более новыми версиями Java кажется не работать (хотя super.helper() делает): «не удается найти символ хелпер()». (Хотя есть что-то странное: после попытки с использованием разных версий Java я не могу получить this.helper(), чтобы скомпилировать с любым из них ...)

ответ

0

Существует article, упоминающий эту проблему, к сожалению, на немецком языке. Возможно, вы все еще можете извлечь полезную информацию.

РЕДАКТОРА: Кажется, это совсем другая проблема. Я все еще не понимаю поведение вашего примера, которое я также вижу здесь.

3

Что-то вроде этого описано в книге Java Puzzlers. IIRC, внешний контекст класса всегда рассматривается перед суперклассом. В этом случае найден хелпер. Но мы строим значение в статическом контексте (там есть private static final до FOO). Отсюда и ошибка.

Пробег: super.helper();.

+0

У меня есть книга; о чем вы говорите? (Я не мог найти его быстро.) – Jonik

+0

Обе мои копии книги упакованы в ящики где-то, поэтому я понятия не имею. –

2

Если я перевожу свой перечисление в своей классовой структуре он будет выглядеть примерно так:

public abstract class TestEnum { 

    public static final TestEnum FOO = new FOO("foo") { 
    public void foo() { 
     helper(); // <- compiler error 
    } 
}; 

    String name; 
    TestEnum(String name) { 
     this.name = name; 
    } 

    public abstract void foo(); 

    private void helper(){ 
    // do stuff (using this.name, so must not be static) 
    } 

}

Экземпляр FOO является anynomous класс, который расширяет TestEnum. Вот почему я считаю, что вы не можете получить доступ к helper(), потому что он является конфиденциальным. Поэтому this.helper(), вероятно, не должен работать. Я не уверен, почему работает super.helper(), но, возможно, enum дает вам частный доступ к родительскому.

Что касается статической ошибки контекста, я согласен, что сообщение об ошибке не имеет смысла.

+0

Nitpick: с «новым FOO» вы имели в виду «новый TestEnum»? – Jonik

+0

да поймал, что тоже .. спасибо – richs

8

Сообщение об ошибке вводит в заблуждение, просто сделайте helper защищенным и будет работать.

protected void helper(){ 
    // can be called from subclasses (such as FOO) since it is not private 
} 
1

Вы можете представить каждую константу enum как единственный экземпляр подкласса класса enum.Подобно «регулярным» классам, «подклассы» перечисления не могут получить доступ к закрытым членам переименования «суперкласс». (Я не могу воссоздать «это». Обходный, что вы говорите.)

разумное решение для изменения доступа метода из частных к охраняемым, чтобы предоставить доступ к перечислимому постоянная " подклассы «.

Лучшее предложение заголовка вопроса: «Java private enum method?» или просто «Private enum method» (пусть Java-тег позаботится о Java-ness)

Смежные вопросы