제네릭을 사용하는 동안 열거 형 값을 반복하는 방법을 찾으려고합니다. 이 작업을 수행하는 방법 또는 가능한지 확실하지 않습니다.
다음 코드는 내가 원하는 것을 보여줍니다. 코드 T.values () 는 다음 코드에서 유효하지 않습니다.
public class Filter<T> {
private List<T> availableOptions = new ArrayList<T>();
private T selectedOption;
public Filter(T selectedOption) {
this.selectedOption = selectedOption;
for (T option : T.values()) { // INVALID CODE
availableOptions.add(option);
}
}
}
필터 개체를 인스턴스화하는 방법은 다음과 같습니다.
Filter<TimePeriod> filter = new Filter<TimePeriod>(TimePeriod.ALL);
열거 형은 다음과 같이 정의됩니다.
public enum TimePeriod {
ALL("All"),
FUTURE("Future"),
NEXT7DAYS("Next 7 Days"),
NEXT14DAYS("Next 14 Days"),
NEXT30DAYS("Next 30 Days"),
PAST("Past"),
LAST7DAYS("Last 7 Days"),
LAST14DAYS("Last 14 Days"),
LAST30DAYS("Last 30 Days");
private final String name;
private TimePeriod(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
열거 형의 값을 목록에 복사하는 것이 이치에 맞지 않을 수도 있지만 값 목록이 입력으로 필요하고 열거 형으로 작동하지 않는 라이브러리를 사용하고 있습니다.
2010 년 2 월 5 일 수정 :
제안 된 대부분의 답변은 매우 유사하며 다음과 같이 제안합니다.
class Filter<T extends Enum<T>> {
private List<T> availableOptions = new ArrayList<T>();
private T selectedOption;
public Filter(T selectedOption) {
Class<T> clazz = (Class<T>) selectedOption.getClass();
for (T option : clazz.getEnumConstants()) {
availableOptions.add(option);
}
}
}
selectedOption에 null이 아닌 값이 있는지 확인할 수 있다면 이것은 잘 작동합니다. 불행히도 내 사용 사례에서는 public Filter () no-arg 생성자 가 있기 때문에이 값은 종종 null 입니다. 이것은 NPE없이 selectedOption.getClass ()를 수행 할 수 없음을 의미합니다. 이 필터 클래스는 어떤 옵션이 선택되었는지 사용 가능한 옵션 목록을 관리합니다. 아무것도 선택하지 않으면 selectedOption은 null입니다.
이 문제를 해결하기 위해 생각할 수있는 유일한 방법은 생성자의 클래스를 실제로 전달하는 것입니다. 그래서 다음과 같이 :
class Filter<T extends Enum<T>> {
private List<T> availableOptions = new ArrayList<T>();
private T selectedOption;
public Filter(Class<T> clazz) {
this(clazz,null);
}
public Filter(Class<T> clazz, T selectedOption) {
this.selectedOption = selectedOption;
for (T option : clazz.getEnumConstants()) {
availableOptions.add(option);
}
}
}
생성자에 추가 클래스 매개 변수가 필요하지 않고이를 수행하는 방법에 대한 아이디어가 있습니까?
답변
이것은 참으로 어려운 문제입니다. 해야 할 일 중 하나는 열거 형을 사용하고 있음을 Java에 알리는 것입니다. 이것은 제네릭에 대한 Enum 클래스를 확장한다는 것을 나타냅니다. 그러나이 클래스에는 values () 함수가 없습니다. 따라서 값을 얻을 수있는 수업을 들어야합니다.
다음 예는 문제 해결에 도움이됩니다.
public <T extends Enum<T>> void enumValues(Class<T> enumType) {
for (T c : enumType.getEnumConstants()) {
System.out.println(c.name());
}
}
답변
또 다른 옵션은 EnumSet을 사용하는 것입니다.
class PrintEnumConsants {
static <E extends Enum <E>> void foo(Class<E> elemType) {
for (E e : java.util.EnumSet.allOf(elemType)) {
System.out.println(e);
}
}
enum Color{RED,YELLOW,BLUE};
public static void main(String[] args) {
foo(Color.class);
}
}
답변
완전성을 위해 JDK8은 values()
Enum 클래스 에서 합성을 사용할 필요없이이를 달성 할 수있는 비교적 깨끗하고 간결한 방법을 제공합니다 .
간단한 열거 형이 주어지면 :
private enum TestEnum {
A,
B,
C
}
그리고 테스트 클라이언트 :
@Test
public void testAllValues() {
System.out.println(collectAllEnumValues(TestEnum.class));
}
다음과 같이 인쇄됩니다 {A, B, C}
.
public static <T extends Enum<T>> String collectAllEnumValues(Class<T> clazz) {
return EnumSet.allOf(clazz).stream()
.map(Enum::name)
.collect(Collectors.joining(", " , "\"{", "}\""));
}
다른 요소를 검색하거나 다른 방식으로 수집하도록 코드를 사소하게 조정할 수 있습니다.
답변
안전하지 않은 캐스트 사용 :
class Filter<T extends Enum<T>> {
private List<T> availableOptions = new ArrayList<T>();
private T selectedOption;
public Filter(T selectedOption) {
Class<T> clazz = (Class<T>) selectedOption.getClass();
for (T option : clazz.getEnumConstants()) {
availableOptions.add(option);
}
}
}
답변
selectedOption
생성자 Filter(T selectedOption)
가 null이 아닌 것이 확실한 경우 . 반사를 사용할 수 있습니다. 이렇게.
public class Filter<T> {
private List<T> availableOptions = new ArrayList<T>();
private T selectedOption;
public Filter(T selectedOption) {
this.selectedOption = selectedOption;
for (T option : this.selectedOption.getClass().getEnumConstants()) { // INVALID CODE
availableOptions.add(option);
}
}
}
도움이 되었기를 바랍니다.
답변
일반 열거 의 값 을 가져 오려면 다음 을 수행하십시오.
protected Set<String> enum2set(Class<? extends Enum<?>> e) {
Enum<?>[] enums = e.getEnumConstants();
String[] names = new String[enums.length];
for (int i = 0; i < enums.length; i++) {
names[i] = enums[i].toString();
}
return new HashSet<String>(Arrays.asList(names));
}
위의 메서드에서 toString () 메서드에 대한 호출에 유의하십시오.
그런 다음 이러한 toString () 메서드를 사용하여 열거 형을 정의합니다.
public enum MyNameEnum {
MR("John"), MRS("Anna");
private String name;
private MyNameEnum(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
답변
근본 문제는 배열을 목록으로 변환해야한다는 것입니다. 그렇죠? 특정 유형 (T 대신 TimePeriod)과 다음 코드를 사용하여이를 수행 할 수 있습니다.
따라서 다음과 같이 사용하십시오.
List<TimePeriod> list = new ArrayList<TimePeriod>();
list.addAll(Arrays.asList(sizes));
이제 목록을 원하는 모든 메소드에 목록을 전달할 수 있습니다.