Development Tip

Java enum과 private 생성자가있는 클래스의 차이점은 무엇입니까?

yourdevel 2020. 12. 25. 10:33
반응형

Java enum과 private 생성자가있는 클래스의 차이점은 무엇입니까?


Java enum이 실제로 어떻게 작동하는지 이해하려고했는데 생성자가 private으로 선언 된 일반 Java 클래스와 매우 유사하다는 결론에 도달했습니다.

방금이 결론에 이르렀고 많은 생각을 바탕으로 한 것이 아니지만 내가 놓친 것이 있는지 알고 싶습니다.

그래서 아래는 간단한 Java 열거 형과 동등한 Java 클래스의 구현입니다.

public enum Direction {
    ENUM_UP(0, -1),
    ENUM_DOWN(0, 1),
    ENUM_RIGHT(1, 0),
    ENUM_LEFT(-1, 0);


    private int x;
    private int y;

    private Direction(int x, int y){
        this.x = x;
        this.y = y;
    }
    public int getEnumX(){
        return x;
    }
    public int getEnumY(){
        return y;
    }
}

위와 아래 코드의 의미 차이는 무엇입니까?

public class Direction{
    public static final Direction UP = new Direction(0, -1) ;
    public static final Direction DOWN = new Direction(0, 1) ;
    public static final Direction LEFT = new Direction(-1, 0) ;
    public static final Direction RIGHT = new Direction(1, 0) ;


    private int x ;
    private int y ;

    private Direction(int x, int y){
        this.x = x ;
        this.y = y ;
    }
    public int getX(){
        return x;
    }
    public int getY(){
        return y;
    }
}

차이점 :

  1. 열거 형은 java.lang.Enum모든 멋진 기능을 확장 하고 얻습니다 .
    1. 올바른 직렬화를 통한 자동 싱글 톤 동작
    2. .toString열거 형 이름을 복제 할 필요없이 열거 형 값에 대해 사람이 읽을 수있는 자동 방법
    3. .name.ordinal특수 목적 방법
    4. 고성능 bitset 기반 EnumSetEnumMap클래스 에서 사용 가능
  2. 열거 형은 언어에 의해 특별히 처리됩니다.
    1. 열거 형은 수십 개의 public static final필드를 작성하지 않고도 인스턴스 생성을 단순화하는 특수 구문을 사용 합니다.
    2. 열거 형은 switch에서 사용할 수 있습니다 .
    3. 리플렉션을 사용하는 경우를 제외하고 열거 형은 열거 형 목록 외부에서 인스턴스화 할 수 없습니다.
    4. 열거 형은 열거 형 목록 외부로 확장 할 수 없습니다.
  3. Java는 추가 항목을 자동으로 enum으로 컴파일합니다.
    1. public static (Enum)[] values();
    2. public static (Enum) valueOf(java.lang.String);
    3. private static final (Enum)[] $VALUES;( values()이것의 복제본을 반환)

이들 중 대부분은 적절하게 설계된 클래스로 에뮬레이션 할 수 있지만, Enum특히 바람직한 속성 집합을 사용하여 클래스를 만들기가 정말 쉽습니다.


질문에 답하기 위해 : 기본적으로 두 접근 방식간에 차이가 없습니다. 그러나 열거 구조 같은 몇 가지 추가 지원 방법을 제공 values(), valueOf()클래스 -와 - 민간 생성자 접근하여 자신에 당신이 작성해야 할 것 등.

하지만 예, 저는 Java enum이 Java의 다른 클래스와 거의 똑같고 필드, 동작 등을 가질 수 있다는 점을 좋아합니다.하지만 enum을 일반 클래스와 구분하는 것은 enum이 인스턴스 / 멤버가있는 클래스 / 유형이라는 생각입니다. 미리 결정됩니다. 인스턴스 수에 제한없이 생성 할 수있는 일반적인 클래스와 달리 열거 형은 생성을 알려진 인스턴스로만 제한합니다. 예, 설명했듯이 개인 생성자를 사용하여 클래스를 사용하여이 작업을 수행 할 수도 있지만 열거 형은이를 더 직관적으로 만듭니다.


한 번 봐 가지고 이 blogpage을 , 그것은 자바 방법을 설명합니다 enum(S)는 바이트 코드로 컴파일됩니다. 당신은 작은 추가는의 배열입니다 두 번째 코드 샘플에 비해이 있다고 볼 수 있습니다 Direction이라고하는 객체 VALUES. 이 배열은 열거 형에 대해 가능한 모든 값을 보유하므로 수행 할 수 없습니다.

new Direction(2, 2)

(예 : 리플렉션 사용) 그런 다음 유효한 Direction으로 사용합니다 .

또한 @ Eng.Fouad가 올바르게 설명했듯이 values(), valueOf()ordinal().


사람들이 지적했듯이 values(), valueOf()그리고 ordinal(). a Map와 a 의 조합을 사용하여이 동작을 매우 쉽게 복제 할 수 있습니다 List.

public class Direction {

    public static final Direction UP = build("UP", 0, -1);
    public static final Direction DOWN = build("DOWN", 0, 1);
    public static final Direction LEFT = build("LEFT", -1, 0);
    public static final Direction RIGHT = build("RIGHT", 1, 0);
    private static final Map<String, Direction> VALUES_MAP = new LinkedHashMap<>();
    private static final List<Direction> VALUES_LIST = new ArrayList<>();
    private final int x;
    private final int y;
    private final String name;

    public Direction(int x, int y, String name) {
        this.x = x;
        this.y = y;
        this.name = name;
    }

    private static Direction build(final String name, final int x, final int y) {
        final Direction direction = new Direction(x, y, name);
        VALUES_MAP.put(name, direction);
        VALUES_LIST.add(direction);
        return direction;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public static Direction[] values() {
        return VALUES_LIST.toArray(new Direction[VALUES_LIST.size()]);
    }

    public static Direction valueOf(final String direction) {
        if (direction == null) {
            throw new NullPointerException();
        }
        final Direction dir = VALUES_MAP.get(direction);
        if (dir == null) {
            throw new IllegalArgumentException();
        }
        return dir;
    }

    public int ordinal() {
        return VALUES_LIST.indexOf(this);
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 29 * hash + name.hashCode();
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Direction other = (Direction) obj;
        return name.equals(other.name);
    }

    @Override
    public String toString() {
        return name;
    }
}

보시다시피, 코드는 매우 빠르게 매우 투박해집니다.

I'm not sure if there is a way for replicate a switch statement with this class; so you will lose that.


The main difference is the each enum class implicitly extends Enum<E extends Enum<E>> class. This leads to that:

  1. enum objects have such methods as name() and ordinal()
  2. enum objects have special toString(), hashCode(), equals() and compareTo() implementations
  3. enum objects are suitable for switch operator.

All mentioned above is not applicable for your version of Direction class. This is the "meaning" difference.

ReferenceURL : https://stackoverflow.com/questions/15734225/what-are-the-differences-between-a-java-enum-and-a-class-with-private-constructo

반응형