Development Tip

Java Generics : 반환 유형으로 만 정의 된 Generic 유형

yourdevel 2020. 11. 11. 20:47
반응형

Java Generics : 반환 유형으로 만 정의 된 Generic 유형


GWT에 대한 GXT 코드를 살펴보고 있으며 Java 자습서에서 다른 예를 찾을 수없는 Generics를 사용했습니다. 클래스 이름은 com.extjs.gxt.ui.client.data.BaseModelData모든 코드를보고 싶은 경우입니다. 다음은 중요한 부분입니다.

private RpcMap map;

public <X> X get(String property) {
  if (allowNestedValues && NestedModelUtil.isNestedProperty(property)) {
    return (X)NestedModelUtil.getNestedValue(this, property);
  }
  return map == null ? null : (X) map.get(property);
}

X클래스의 다른 곳이나 계층의 어디에도 정의되어 있지 않으며, 이클립스에서 "선언으로 이동" <X>을 누르면 공용 메서드 서명으로 이동합니다.

다음 두 가지 예를 사용하여이 메서드를 호출하여 어떤 일이 발생하는지 확인했습니다.

public Date getExpiredate() {
    return  get("expiredate");
}

public String getSubject() {
    return  get("subject");
}

컴파일하고 오류나 경고를 표시하지 않습니다. 나는 이것이 작동하도록 적어도 나는 캐스트를해야한다고 생각할 것입니다.

이것은 Generics가 무엇이든 될 수있는 매직 리턴 값을 허용하고 런타임에 폭발 할 것이라는 것을 의미합니까? 이것은 제네릭이해야 할 일과 반대되는 것 같습니다. 누구든지 이것을 나에게 설명하고 아마도 이것을 좀 더 잘 설명하는 문서에 대한 링크를 줄 수 있습니까? 제네릭에 대한 Sun의 23 페이지 pdf를 살펴 보았고 반환 값의 모든 예는 클래스 수준에서 정의되거나 전달 된 매개 변수 중 하나에 있습니다.


이 메서드는 예상되는 모든 유형을 반환합니다 ( <X>메서드에 정의되어 있으며 절대적으로 제한되지 않음).

반환 유형이 실제로 반환 된 값과 일치한다는 규정이 없기 때문에 매우 위험합니다.

이것이 갖는 유일한 장점은 모든 유형을 반환 할 수있는 이러한 일반 조회 메서드의 반환 값을 캐스팅 할 필요가 없다는 것입니다.

나는 말하고 싶다 : 당신은 거의 모든 유형 안전성을 잃고 .NET을 호출 할 때마다 명시 적으로 캐스트를 작성할 필요가 없다는 것만 얻을 수 있기 때문에 신중하게 그러한 구조를 사용하십시오 get().

그리고 예 : 이것은 거의 런타임에 폭발하고 제네릭이 달성해야하는 전체 아이디어를 깨뜨리는 흑 마법입니다.


형식은 메서드에서 선언됩니다. 그것이 " <X>"의 의미입니다. 유형은 메소드로만 범위가 지정되고 특정 호출과 관련됩니다. 테스트 코드가 컴파일되는 이유는 컴파일러가 유형을 결정하려고 시도하고 불가능한 경우에만 불평하기 때문입니다. 명시 적이어야하는 경우가 있습니다.

예를 들어에 대한 선언 Collections.emptySet()은 다음과 같습니다.

public static final <T> Set<T> emptySet()

이 경우 컴파일러는 다음을 추측 할 수 있습니다.

Set<String> s = Collections.emptySet();

그러나 할 수없는 경우 다음을 입력해야합니다.

Collections.<String>emptySet();

나는 GXT 수업에서 똑같은 것을 알아 내려고했다. 특히 다음 서명을 사용하여 메서드를 호출하려고했습니다.

class Model {
    public <X> X get(String property) { ... }
}

코드에서 위의 메서드를 호출하고 X를 문자열로 캐스트하려면 다음을 수행합니다.

public String myMethod(Data data) {
    Model model = new Model(data);
    return model.<String>get("status");
}

위의 코드는 get 메서드를 호출하고 X에서 반환하는 형식을 문자열로 반환해야한다고 알려줍니다.

메서드가 여러분과 같은 클래스에있는 경우 "this."로 호출해야한다는 것을 알았습니다. 예를 들면 :

this.<String>get("status");

다른 사람들이 말했듯이 이것은 GXT 팀에 의해 다소 조잡하고 위험합니다.


BaseModelData는 안전하지 않기 때문에 컴파일 될 때 확인되지 않은 경고를 발생시킵니다. 이와 같이 사용하면 코드 자체에 경고가 없더라도 런타임에 ClassCastException이 발생합니다.

public String getExpireDate() {
  return  get("expiredate");
}

RpcMap (GXT API 1.2)의 흥미로운 메모

get의 헤더 :

public java.lang.Object get(java.lang.Object key)

Having a generic parameter of <X> in there that's uninstantiated has the same effect, except you don't have to say "Object" all over the place. I agree with the other poster, this is sloppy and a bit dangerous.


Yes, this is dangerous. Normally, you'd protect this code like so:

<X> getProperty(String name, Class<X> clazz) {
   X foo = (X) whatever(name);
   assert clazz.isAssignableFrom(foo);
   return foo;
}

String getString(String name) {
  return getProperty(name, String.class);
}

int getInt(String name) {
  return getProperty(name, Integer.class);
}

참고URL : https://stackoverflow.com/questions/338887/java-generics-generic-type-defined-as-return-type-only

반응형