Java открытый метод enum назначение - PullRequest
11 голосов
/ 30 августа 2011

Итак, у меня есть мой enum

public enum Sample {
   ValueA{
      @Override
   public String getValue(){ return "A"; }   
 },
 ValueB{
    @Override
   public String getValue(){ return "B"; }

   public void doSomething(){ }
 };
abstract public String getValue();
};

и у меня есть другой код, пытающийся использовать перечисление.

Sample.ValueB.doSomething();

Кажется, что он должен быть действительным, но выдает ошибку «Метод doSomething () не определен для типа Sample». В отличие от

Sample value = Sample.ValueB;
value.doSomething();

, которая выдает ту же ошибку и кажется разумной.

Я предполагаю, что есть разумный ответ относительно того, почему первый не работает, и это относится к двум примерам, эквивалентным под капотом. Я надеялся, что кто-то может указать мне на документацию о том, почему это так.

Ответы [ 4 ]

15 голосов
/ 30 августа 2011

Тип "поля" ValueA равен Sample.Это означает, что вы можете вызывать только те методы ValueA, которые предоставляет Sample JLS § 8.9.1.Константы перечисления :

Методы экземпляра, объявленные в этих телах классов, могут вызываться вне включающего типа перечисления, только если они переопределяют доступные методы в включающем типе перечисления.

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

10 голосов
/ 30 августа 2011

Обычно тип времени компиляции из Sample.ValueB по-прежнему является Sample, хотя тип значения время выполнения будет ValueB.Таким образом, ваши два фрагмента кода эквивалентны - клиенты не видят «дополнительные» методы, которые присутствуют только в некоторых ваших значениях перечисления.

Вы можете эффективно думать оперечисление как объявление поля как это:

public static final Sample ValueB = new Sample() {
    @Override
    public String getValue(){ return "B"; }

    public void doSomething(){ }
};
4 голосов
/ 30 августа 2011

Когда вы пишете

enum Sample
{
     Value{
        public void doSomething()
        {
              //do something
        }
    };
}

вы не создаете экземпляр перечисления Sample, а скорее экземпляр анонимного подкласса enum Sample. Вот почему метод doSomething() не определен.

Обновление: это может быть доказано следующим образом:

Попробуйте это

System.out.println(Sample.ValueB.getClass().getName());

отпечатки Sample$2

Это означает, что даже если у вас есть метод doSomething() в случае Sample$2, который вы назвали ValueB, вы ссылаетесь на него через ссылку на суперкласс типа Sample и, следовательно, только на эти методы определенный в классе Sample будет виден во время компиляции.

Вы можете назвать это doSomething() во время выполнения через отражение.

3 голосов
/ 30 августа 2011

public void doSomething(){ } будет иметь тот же эффект, что и private void doSomething(){ }.

doSomething() не отображается за пределами ValueB, если вы не добавите doSomething() к Sample.

Каждое Sample значение имеет тип Sample, поэтому оно не может иметь разный набор методов для разных значений (с внешней точки зрения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...