Java 열거형에서 일반 유형 매개 변수를 사용할 수 없는 이유는 무엇입니까?
자바 enum은 훌륭합니다.제네릭도 마찬가지입니다.물론 우리는 활자 삭제로 인해 후자의 한계를 알고 있다.하지만 한 가지 이해가 가지 않는 것이 있습니다.왜 다음과 같은 열거형을 만들 수 없는가?
public enum MyEnum<T> {
LITERAL1<String>,
LITERAL2<Integer>,
LITERAL3<Object>;
}
이 범용 유형 매개 변수<T>
그러면 다양한 장소에서 유용하게 쓰일 수 있을 것이다.메서드에 대한 범용 유형 매개 변수를 상상해 보십시오.
public <T> T getValue(MyEnum<T> param);
enum 클래스 자체에서도 마찬가지입니다.
public T convert(Object o);
보다 구체적인 예 #1
위의 예제가 너무 추상적으로 보일 수 있기 때문에, 제가 왜 이것을 하고 싶은지에 대한 더 실제적인 예를 제시하겠습니다.이 예에서는 다음을 사용합니다.
- Enums, 그러면 유한한 속성 키 집합을 열거할 수 있습니다.
- 일반, 그러면 속성을 저장하기 위한 방법 수준 유형 안전성을 가질 수 있습니다.
public interface MyProperties {
public <T> void put(MyEnum<T> key, T value);
public <T> T get(MyEnum<T> key);
}
보다 구체적인 예 2
다음과 같은 데이터 유형이 열거되어 있습니다.
public interface DataType<T> {}
public enum SQLDataType<T> implements DataType<T> {
TINYINT<Byte>,
SMALLINT<Short>,
INT<Integer>,
BIGINT<Long>,
CLOB<String>,
VARCHAR<String>,
...
}
각 enum 리터럴 분명히 추가 속성은 제네릭 형식에 따랐을 것이다.<T>
같은 시간에 있는 동안,는 enum(, 독신자, 열거 가능한 등 등 불변의).
질문:.
이 가진 적이 있었나 사람이 없다고 생각합니까?이것은compiler-related 무엇인가?는 키워드"enum"구문 설탕처럼 실행하는 JVM에 생성된 코드를 나타내는 사실을 고려해 볼 때, 이러한 한계들을 이해하지 않는다.
누가 나에게 이 설명할 수 있을까?전에 대답하시기:이 것이 좋습니다.
- 나는 제네릭 형식:-)이 삭제됩니다 알고 있다.
- 나는 워크 어라운드 그리고 설명 클래스 개체를 사용하는 것을 안다.그들은 차선책.
- 제네릭 형식compiler-generated 형식 출연하는 곳 어디에나 적용 가능한(예를 들었다. 이 때 전향자 전화()메서드의 결과가 된다.
- 제네릭 형식<>T>은 enum 것이다.따라서 각 enum의 오며 리터럴의 준수하고 있다.따라서 컴파일러, 같은 무언가를 쓰고 적용하는지 알것이다.
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
- 이와 같은 것이 제네릭 형식 매개 변수에 대한에 적용된다.
T getvalue()
방법.컴파일러는 형식하며 호출 시 주조 적용할 수 있습니다.String string = someClass.getValue(LITERAL1)
이 JEP-301의 강화된 Enums는 세컨 비자가 취소되었음을 유감스럽게도의로 토론되어 왔다.이 예제는 초등 학생에 주어지는 것이 정확히 제가 찾고자 하는 것은 있다.
enum Argument<X> { // declares generic enum
STRING<String>(String.class),
INTEGER<Integer>(Integer.class), ... ;
Class<X> clazz;
Argument(Class<X> clazz) { this.clazz = clazz; }
Class<X> getClazz() { return clazz; }
}
Class<String> cs = Argument.STRING.getClazz(); //uses sharper typing of enum constant
불행히도 초등 학생을 해결 할 수가 없는 중요한 문제:http://mail.openjdk.java.net/pipermail/amber-spec-experts/2017-May/000041.html에 발버둥 치고 있었다
답은 이 질문에 있습니다.
활자 삭제 때문에
인수 유형이 지워지기 때문에 이러한 두 가지 방식 중 어느 것도 가능하지 않습니다.
public <T> T getValue(MyEnum<T> param);
public T convert(Object);
그러나 이러한 방법을 실현하려면 다음과 같이 열거를 구성할 수 있습니다.
public enum MyEnum {
LITERAL1(String.class),
LITERAL2(Integer.class),
LITERAL3(Object.class);
private Class<?> clazz;
private MyEnum(Class<?> clazz) {
this.clazz = clazz;
}
...
}
당신은 그럴수 없기 때문이다.정말이에요.그것은 언어 사양에 추가될 수 있습니다.그렇지 않다.복잡성이 더해져요비용 대비 편익은 높은 우선순위가 아니라는 것을 의미합니다.
업데이트: 현재 JEP 301: Enhanced Enums에서 언어에 추가 중입니다.
ENUM을 사용하다어떻게 하면 좋을까?MyEnum.values()
반하?????
★★는?MyEnum.valueOf(String name)
컴파일러가 다음과 같은 범용 메서드를 만들 수 있다고 생각되는 경우 값 Of.
퍼블릭 스태틱 MyEnum 값 Of(문자열 이름);
라고 MyEnum<String> myStringEnum = MyEnum.value("some string property")
, 「」를 호출했을 는, 「」를 참조해 주세요.MyEnum<Int> myIntEnum = MyEnum.<Int>value("some string property")
수 없습니다.를 들어, 예외나 때 null을 할 수 없습니다MyEnum.<Int>value("some double property")
활자 삭제 때문에.
솔직히 이것은 그 어떤 것보다도 문제를 찾는 해결책처럼 보인다.
Java Enum의 전체 목적은 유사한 속성을 공유하는 유형 인스턴스의 열거를 모델화하는 것입니다.이것에 의해, 동등한 String 또는 Integer 표현보다 일관성과 풍부함을 얻을 수 있습니다.
교과서 열거의 예를 들어 보겠습니다.이것은 그다지 유용하거나 일관성이 없습니다.
public enum Planet<T>{
Earth<Planet>,
Venus<String>,
Mars<Long>
...etc.
}
행성마다 일반 유형 변환이 달라야 하는 이유는 무엇입니까?어떤 문제가 해결됩니까?언어 의미론을 복잡하게 만드는 것이 정당화됩니까?이 동작이 필요한 경우 이를 실현하기 위한 최선의 툴은 열거형입니까?
또한 복잡한 변환은 어떻게 관리합니까?
예를 들어.
public enum BadIdea<T>{
INSTANCE1<Long>,
INSTANCE2<MyComplexClass>;
}
이면 충분합니다String
Integer
이름 또는 서수를 제공합니다.하지만 제네릭스는 어떤 타입이든 공급할 수 있습니다.MyComplexClass
컴파일러가 범용 에넘에 공급 가능한 타입의 서브셋이 한정되어 있다는 것을 알게 하고, 이미 많은 프로그래머를 따돌리고 있는 것 같은 개념(Generics)에 추가적인 혼란을 초래함으로써 두 가지 구성을 혼란스럽게 합니다.
이 Java 주석 프로세서 https://github.com/cmoine/generic-enums,을 사용하면 다음과 같은 내용을 쓸 수 있습니다(변환 메서드는 예로 구현되었습니다).
import org.cmoine.genericEnums.GenericEnum;
import org.cmoine.genericEnums.GenericEnumParam;
@GenericEnum
public enum MyEnum {
LITERAL1(String.class) {
@Override
@GenericEnumParam
public Object convert(Object o) {
return o.toString(); // example
}
},
LITERAL2(Integer.class) {
@Override
@GenericEnumParam
public Object convert(Object o) {
return o.hashCode(); // example
}
},
LITERAL3(Object.class) {
@Override
@GenericEnumParam
public Object convert(Object o) {
return o; // example
}
};
MyEnum(Class<?> clazz) {
}
@GenericEnumParam
public abstract Object convert(Object o);
}
합니다.MyEnumExt
Java Enum을 사용합니다.열거형으로 할 수 있는 클래스가 됩니다).Enum
"enum"은 열거의 약어이기 때문입니다.코드 가독성을 높이기 위해 서수 대신 서 있는 이름 있는 상수의 집합일 뿐입니다.
유형 매개 변수 상수의 의도된 의미가 무엇인지 알 수 없습니다.
기본적으로 Enums는 인스톨 할 수 없기 때문에
JVM에서 T클래스를 설정할 수 있다면 어디에 설정하시겠습니까?
열거는 항상 같거나 적어도 2진법으로 변경되지 않아야 하는 데이터입니다.
새로운 MyEnum <>(?)
그래도 다음과 같은 접근법이 유용할 수 있습니다.
public enum MyEnum{
LITERAL1("s"),
LITERAL2("a"),
LITERAL3(2);
private Object o;
private MyEnum(Object o) {
this.o = o;
}
public Object getO() {
return o;
}
public void setO(Object o) {
this.o = o;
}
}
언급URL : https://stackoverflow.com/questions/4290878/why-shouldnt-java-enum-literals-be-able-to-have-generic-type-parameters
'programing' 카테고리의 다른 글
사용되지 않는 JPMS 모듈을 Java EE API로 대체 (0) | 2022.08.15 |
---|---|
즐겨찾기에 동영상 추가 (0) | 2022.08.15 |
계산된 속성을 모든 구성 요소에 사용할 수 있도록 설정 (0) | 2022.08.08 |
vue.js 컴포넌트를 애플리케이션 루트에 마운트합니다. (0) | 2022.08.08 |
영어 대신 중국어로 된 요소 UI 페이지 표시 (0) | 2022.08.08 |