Programing

Java 6 열거 형에 대한 values ​​()는 어떻게 구현됩니까?

crosscheck 2020. 11. 15. 10:55
반응형

Java 6 열거 형에 대한 values ​​()는 어떻게 구현됩니까?


Java에서는 다음과 같이 열거 형을 만들 수 있습니다.

public enum Letter {
    A, B, C, D, E, F, G;

    static {
       for(Letter letter : values()) {
          // do something with letter
       }
    }
}

이 질문은 "values ​​()"메소드에 관한 것입니다. 구체적으로 어떻게 구현됩니까? 일반적으로 Eclipse에서 F3 또는 CTRL + Click을 사용하여 Java 클래스의 소스로 이동할 수 있습니다 (String, Character, Integer 및 Enum과 같은 클래스의 경우에도). 다른 enum 메서드 (예 : valueOf (String))의 소스를 볼 수 있습니다.

"values ​​()"는 호출 될 때마다 새 배열을 생성합니까? 지역 변수에 할당 한 다음 요소 중 하나를 수정하면 어떤 일이 발생합니다 (분명히 이것은 values ​​()에 의해 반환 된 값에 영향을 미치지 않으며 매번 새 배열이 할당됨을 의미합니다).

코드가 네이티브인가요? 또는 JVM / 컴파일러가이를 특별히 처리하고 수정되지 않을 것이라는 것을 증명할 수없는 경우에만 values ​​()에서 새 인스턴스를 반환합니다.


기본적으로 컴파일러 (javac)는 컴파일 타임에 모든 값을 포함하는 정적 배열로 열거 형을 변환합니다. values ​​()를 호출하면이 배열의 .clone'd () 복사본이 제공됩니다.

이 간단한 열거 형이 주어지면 :

public enum Stuff {
   COW, POTATO, MOUSE;
}

실제로 Java가 생성하는 코드를 볼 수 있습니다.

public enum Stuff extends Enum<Stuff> {
    /*public static final*/ COW /* = new Stuff("COW", 0) */,
    /*public static final*/ POTATO /* = new Stuff("POTATO", 1) */,
    /*public static final*/ MOUSE /* = new Stuff("MOUSE", 2) */;
    /*synthetic*/ private static final Stuff[] $VALUES = new Stuff[]{Stuff.COW, Stuff.POTATO, Stuff.MOUSE};

    public static Stuff[] values() {
        return (Stuff[])$VALUES.clone();
    }

    public static Stuff valueOf(String name) {
        return (Stuff)Enum.valueOf(Stuff.class, name);
    }

    private Stuff(/*synthetic*/ String $enum$name, /*synthetic*/ int $enum$ordinal) {
        super($enum$name, $enum$ordinal);
    }
}

임시 디렉토리를 만들고 다음을 실행하여 javac가 클래스를 '번역'하는 방법을 볼 수 있습니다.

javac -d <output directory> -XD-printflat filename.java

로컬 변수에 할당하는 경우 수정할 수있는 유일한 것은이 변수에 다른 열거 형을 할당하는 것입니다. 변수가 참조하는 개체 만 변경하기 때문에 열거 형 자체는 변경되지 않습니다.

열거 형은 실제로 단일 항목이므로 각 열거 형의 한 요소 만 전체 프로그램에 존재할 수 있으므로 == 연산자가 열거 형에 합법적으로 적용됩니다.

따라서 성능 문제가 없으며 enum 정의에서 실수로 무언가를 변경할 수 없습니다.


코드가 네이티브인가요? 또는 JVM / 컴파일러가이를 특별히 처리하고 수정되지 않을 것이라는 것을 증명할 수없는 경우에만 values ​​()에서 새 인스턴스를 반환합니다.

1) 아니요. 또는 적어도 현재 구현에서는 아닙니다. 증거는 @lucasmo의 답변을 참조하십시오.

2) AFAIK, 아니요.

가설 적으로 그렇게 할 수 있습니다. 그러나 어레이가 로컬에서 수정되지 않는다는 것을 증명하는 것은 복잡하고 JIT가 수행하는 데 상대적으로 비용이 많이 듭니다. 을 호출 한 메서드에서 배열이 "탈출" values()하면 더 복잡하고 비용이 많이 듭니다.

이 (가상) 최적화가 모든 Java 코드에 대해 평균을 낼 때 효과가 없을 가능성이 있습니다.

The other issue is that this (hypothetical) optimization might open up security holes.


The interesting thing though is that the JLS does not seem to specify that the values() member returns an array copy. Common sense1 says that it must do ... but it is not actually specified.

1 - It would be a gaping security hole if values() returned a shared (mutable) array of enum values.

참고URL : https://stackoverflow.com/questions/1163076/how-is-values-implemented-for-java-6-enums

반응형