developer tip

Java에서 런타임에 열거 요소를 추가하고 제거 할 수 있습니까?

copycodes 2021. 1. 8. 08:32
반응형

Java에서 런타임에 열거 요소를 추가하고 제거 할 수 있습니까?


런타임에 Java의 열거 형에서 요소를 추가하고 제거 할 수 있습니까?

예를 들어 파일에서 열거 형의 레이블 및 생성자 인수를 읽을 수 있습니까?


@saua, 그것은 정말로 흥미로울 수 있는지 여부에 대한 질문입니다. BCEL 등을 사용하여 실행중인 바이트 코드를 변경하는 깔끔한 방법이 있기를 바랐습니다 . 나는 또한 enum을 사용해야 할 때가 확실하지 않다는 것을 깨달았 기 때문에이 질문을 계속했습니다 .

런타임에 내용을 안전하게 변경하려면 열거 형 대신 고유성을 보장하는 컬렉션을 사용하는 것이 정답 일 것이라고 확신합니다.


아니요, 열거 형은 완전한 정적 열거 형이어야합니다.

컴파일 타임에 어떤 종류의 다른 소스 파일에서 열거 형 .java 파일을 생성 할 수 있습니다. 이와 같은 .class 파일을 만들 수도 있습니다.

어떤 경우에는 표준 값 세트를 원하지만 확장을 허용 할 수 있습니다. 이를 수행하는 일반적인 방법 interface은 인터페이스에 대한를 사용하고 표준 값에 대해 enum이를 구현하는 것 interface입니다. 물론, 당신은 할 수있는 기능 상실 switch당신은 단지에 대한 참조가있을 때를 interface.


커튼 뒤에서 열거 형은 개인 생성자와 열거 형 유형의 공개 정적 최종 값이있는 POJO입니다 ( 예는 여기 참조 ). 사실 Java5까지는 이러한 방식으로 고유 한 열거 형을 작성하는 것이 모범 사례로 간주되었으며 Java5는 enum키워드를 속기로 도입했습니다 . 자세한 내용은 Enum <T> 의 소스를 참조하십시오 .

따라서 생성자에 의해 읽히거나 전달되는 상수의 공개 정적 최종 배열을 사용하여 고유 한 'TypeSafeEnum'을 작성하는 것은 문제가되지 않습니다.

또한 자신에게 호의를 베풀고 equals, hashCode및을 재정의 toString하고 가능하면 values메서드를 만듭니다.

문제는 이러한 동적 열거를 사용하는 방법입니다 ... 파일에서 "PI = 3.14"값을 읽어 생성 enum MathConstants한 다음 MathConstants.PI원하는 곳에서 사용할 수 없습니다.


(단위 테스트 목적으로) 이와 같은 작업을 수행해야했고이 EnumBuster를 발견했습니다. http://www.javaspecialists.eu/archive/Issue161.html

열거 형 값을 추가, 제거 및 복원 할 수 있습니다.

편집 : 나는 방금 이것을 사용하기 시작했으며 현재 Java 1.5에 필요한 약간의 변경이 있음을 발견했습니다.

  • 정적 도우미 메서드의 배열 사본 추가 (예 : 다음 1.6 버전 사용 : http://www.docjar.com/html/api/java/util/Arrays.java.html )
  • EnumBuster.undoStack을 스택으로 변경<Memento>
    • undo ()에서 undoStack.poll ()을 undoStack.isEmpty ()로 변경합니까? null : undoStack.pop ();
  • 지금까지 시도한 Java 1.5 열거 형의 경우 VALUES_FIELD 문자열은 "ENUM $ VALUES"여야합니다.

나는 젊은 경력조형 프로젝트 에서이 문제에 직면했다 .

내가 취한 접근 방식은 값과 열거 형의 이름을 외부에 저장하는 것이었고 최종 목표는 가능한 한 언어 열거 형에 가까운 코드를 작성할 수있는 것이 었습니다.

내 솔루션이 다음과 같기를 원했습니다.

enum HatType
{
    BASEBALL,
    BRIMLESS,
    INDIANA_JONES
}

HatType mine = HatType.BASEBALL;

// prints "BASEBALL"
System.out.println(mine.toString());

// prints true
System.out.println(mine.equals(HatType.BASEBALL));

그리고 나는 다음과 같은 결과를 얻었습니다.

// in a file somewhere:
// 1 --> BASEBALL
// 2 --> BRIMLESS
// 3 --> INDIANA_JONES

HatDynamicEnum hats = HatEnumRepository.retrieve();

HatEnumValue mine = hats.valueOf("BASEBALL");

// prints "BASEBALL"
System.out.println(mine.toString());

// prints true
System.out.println(mine.equals(hats.valueOf("BASEBALL"));

내 요구 사항은 런타임에 열거 형에 멤버를 추가 할 수 있어야한다는 것이었기 때문에 해당 기능도 구현했습니다.

hats.addEnum("BATTING_PRACTICE");

HatEnumRepository.storeEnum(hats);

hats = HatEnumRepository.retrieve();

HatEnumValue justArrived = hats.valueOf("BATTING_PRACTICE");
// file now reads:
// 1 --> BASEBALL
// 2 --> BRIMLESS
// 3 --> INDIANA_JONES
// 4 --> BATTING_PRACTICE

나는 그것을 Dynamic Enumeration "pattern"이라고 불렀고, 당신 은 원래 디자인그것의 개정판에 대해 읽었습니다 .

The difference between the two is that the revised edition was designed after I really started to grok OO and DDD. The first one I designed when I was still writing nominally procedural DDD, under time pressure no less.


You can load a Java class from source at runtime. (Using JCI, BeanShell or JavaCompiler)

This would allow you to change the Enum values as you wish.

Note: this wouldn't change any classes which referred to these enums so this might not be very useful in reality.


You could try to assign properties to the ENUM you're trying to create and statically contruct it by using a loaded properties file. Big hack, but it works :)

ReferenceURL : https://stackoverflow.com/questions/478403/can-i-add-and-remove-elements-of-enumeration-at-runtime-in-java

반응형