Доступ к пользовательским перечисляемым полям

#java #enums

#java #перечисления

Вопрос:

Как я могу получить доступ (без отражения) RAIN и WIND поля из какого-либо другого класса? Моя среда разработки показывает ошибки, когда я пытаюсь ссылаться Season.FALL.RAIN на , Season.FALL.WIND , и вызывать Season.FALL.getWind() . Season enum компилируется нормально:

 public enum Season {
  WINTER,
  SPRING,
  SUMMER,
  FALL {
    public static final String RAIN = "rain";
    public final String WIND = "wind";

    public String getWIND() {
      return WIND;
    }
  };
}
  

Почему Java разрешает эти элементы, если я не могу получить к ним доступ извне? Я не могу получить к ним доступ даже внутри Season перечисления. Я использую Java 11.

Ответ №1:

Это связано с тем, что класс FALL константы является подклассом Season класса — вы можете представить его, поскольку вы объявили его как анонимный класс.

Вы можете эмулировать подобную ситуацию и без перечислений:

     public static void main(String[] args) {
        class C {
            public int i;
        }
        C c = new C() {
            public int a;
        };
        System.out.println(c.a); // wont compile
    }
  

c Экземпляр по-прежнему обрабатывается как C класс (несмотря на то, что фактический класс является чем-то вроде C$1 ), и a в классе нет поля C . Java позволяет a field обслуживать членов подкласса, а не кого-либо извне. Подкласс существует, но недоступен буквально. Возможен доступ к отражению. То же самое относится и к вашему примеру перечисления.

Комментарии:

1. После этого я должен добавить небольшое примечание: есть разница между моим примером и Season примером enum. Это класс, созданный за сценой, тогда как это явно определенный анонимный класс. Season.FALL.getClass() C$1 Я могу изменить объявление C c на var c в моем примере, и код становится компилируемым (см. nipafx.dev/java-var-anonymous-classes-tricks для лучшего объяснения этого трюка). Я не могу придумать, как применить этот трюк для захвата класса FALL константы перечисления.

Ответ №2:

Для определения также внутренних атрибутов как enum это будет работать:

     enum Season {
        UNDEFINED,
        WINTER(Phenomenon.RAIN),
        SPRING(Phenomenon.WIND),
        SUMMER(Phenomenon.HOT),
        FALL(Phenomenon.RAIN, Phenomenon.WIND);

        enum Phenomenon {
            RAIN,
            WIND,
            HOT
        };

        Phenomenon[] phenomena;

        Season(Phenomenon... phenomena) {
            this.phenomena = phenomena;
        }

        @Override
        public String toString() {
            return this.name()   ":  "   Arrays.toString(phenomena);
        }
    }
  

Затем печать / поиск:

         for (Season s : Season.values()) {
            System.out.println(s);
        }
        System.out.println();

        Season s = Season.SPRING;
        for (Phenomenon p : new Phenomenon[] { Phenomenon.HOT, Phenomenon.WIND }) {
            if (Arrays.binarySearch(s.phenomena, p) >= 0) {
                System.out.println(String.format("Phenomenon [%s] happens in season [%s]", p, s.name()));
            } else {
                System.out.println(String.format("Phenomenon [%s] does not happen in season [%s]", p, s.name()));
            }
        }

  

будет выводить:

 UNDEFINED:  []
WINTER:  [RAIN]
SPRING:  [WIND]
SUMMER:  [HOT]
FALL:  [RAIN, WIND]

Phenomenon [HOT] does not happen in season [SPRING]
Phenomenon [WIND] happens in season [SPRING]
  

Ответ №3:

Не уверен, почему вы хотите это сделать, но вы можете сделать это так:

 public enum Season {
  WINTER,
  SPRING,
  SUMMER,
  FALL;
  public static final String RAIN = "rain";
  public static final String WIND = "wind";
}
  

Если вы хотите, чтобы эти два поля были доступны только в FALL , это невозможно. Каждое значение перечисления относится к одному и тому же конечному классу, и если у вас есть статическое поле в классе, оно доступно независимо от того, на какое значение класса вы ссылаетесь.

Ответ №4:

Это потому, что объявление Season не принимает эти методы и свойства.

Попробуйте создать более подробное перечисление, например:

 public enum Season {
  WINTER,
  SPRING,
  SUMMER,
  FALL("rain", "wind");
  
  
  private String rain;
  private String wind;
  
  
  private Season () {}
  
  private Season(String rain, String wind) {
      this.rain = rain;
      this.wind = wind;
  }
  
  public String getRain() { return this.rain; }
  public String getWind() { return this.wind; }
}
  

Таким образом, вы можете получить доступ к этим свойствам следующим образом:

 System.out.println(Season.FALL.getRain());