2011-12-09 3 views
9

유형 삭제를 피하고 유형 매개 변수에 액세스 할 수있는 방법이 있습니까?자바 유형 삭제 방지

public class Foo<T extends Enum<?> & Bar> { 
    public Foo() { 
     // access the template class here? 
     // i.e. : 
     baz(T.class); // obviously doesn't work 
    } 

    private void baz(Class<T> qux) { 
     // do stuff like 
     T[] constants = qux.getEnumConstants(); 
     ... 
    } 
} 

T에 대해 알아야하며 이에 대해 알아야합니다. 가능하면 그렇다면 없이 생성자의 클래스에서 전달하거나 매개 변수 외의 다른 곳에서 전달할 수 있습니까?

편집 :이 질문의 주요 목적은 형의 삭제 주변에있는 실제적인 방법이 있는지 확인하는 것입니다.

답변

5

AFACT : 여기에 자체 포함 된 예입니다. 물론 당신은 Bar 인터페이스를 구현하는 각 열거 형의 하위 클래스를 generic class로 분류하는 것이 실용적인 해결책이라는 데 동의합니다.

enum Test implements Bar { 
    ONE, TWO 
} 

class Foo<T> extends FooAbstract<Test> { 
    public Foo() { 
     ParameterizedType genericSuperclass = 
       (ParameterizedType) getClass().getGenericSuperclass(); 
     baz((Class<T>) genericSuperclass.getActualTypeArguments()[0]); 
    } 

    private void baz(Class<T> qux) { 
     T[] constants = qux.getEnumConstants(); 
     System.out.println(Arrays.toString(constants)); // print [ONE, TWO] 
    } 
} 

interface Bar { 
} 

class FooAbstract<T extends Enum<?> & Bar> { 
} 
+2

한 네는 - 당신이'Class' 객체를 전달하는 서브 클래스를 선호하는 경우 이것은 또 다른 반사 기반의 대안이다. –

2

당신은 클래스 생성자에 토큰 손 수/기꺼이 경우

public Foo(Class<T> clazz) { 
    baz(clazz); 
} 

private void baz(Class<T> qux) { 
    // ... 
} 

그런 식으로, 당신은 것은 Class.newInstance()에 임의의 객체를 캐스팅 시도와 T 타입의 객체를 생성 할 수 있습니다 T는 Class.cast() 등을 사용합니다.

baz()에서 무엇을 할 계획입니까?

+0

주어진 클래스에 값 목록을 요청하고 해당 값을 사용한다고 가정 해 보겠습니다. 수업에 합격하는 것이 내가하고 싶은 것이 아닙니다. –

1

답변에서 folser가 지적한 것처럼 T을 나타내는 Class 개체를 전달하면됩니다. Type Erasure 때문에 런타임 전에 T이 지워지기 때문에 T.class과 같은 것을 사용할 수 없습니다.

Class 개체를 통과하는 것에 대해 내성이 있지만, getEnumConstants() 메서드를 사용하는 유일한 방법입니다. 당신이 런타임에 액세스 할 수없는 뭔가를 요청할 수 없기 때문에 형의 삭제 주위 실제적인 방법이 없다,

public class Foo<T extends Enum<?> & Bar> { 

    final Class<T> clazz; 

    public Foo(Class<T> clazz) { 

     this.clazz = clazz; 
    } 

    public void baz() { 

     T[] constants = clazz.getEnumConstants(); 

     System.out.println(Arrays.toString(constants)); 
    } 

    public static void main(String[] args) { 

     new Foo<MyEnum>(MyEnum.class).baz(); //prints "[A, B, C, D]" 
    } 
} 

public interface Bar { } 

public enum MyEnum implements Bar { A, B, C, D; } 
+2

그래서 타입 지우기를 둘러보고 클래스가 'T'로 전달 된 것을 알 수있는 방법은 없습니다.이 스레드의 아이디어는 유형 삭제 주변에 어떤 방법이 있는지 알아 보는 것입니다. –

+1

@Chris - Reflection은 Java에서 삭제를 입력하는 유일한 방법입니다. 그러나 당신은 성가신 및 컴파일 시간에 중복 보이지만 당신의'Class' 객체를 전달하여 무슨에서 더 이상 불이익을 넣어 것입니다. 이미 클래스 # getEnumConstants()를 사용하여 리플렉션에 의존하고 있음을 주목하십시오. 유일한 대안은 해당 방법에 대한 의존성을 제거하는 완전한 재 설계입니다. –

1

Neil Gafter의 제안에 따라 super type 토큰을 사용하고 guice와 같은 라이브러리에서이 용도로 사용합니다.

원래 설명을 보려면 http://gafter.blogspot.com/2006/12/super-type-tokens.html을 참조하십시오. CA 무선 수명 작동 구현을위한 guice 소스를 확인했습니다.

당신은 리처드 고메스에 의해 제안 해결 방법을 사용할 수있는 몇 가지 경우에 인라인 여기 How can I pass a Class as parameter and return a generic collection in Java?

0

일 예에 대한 답을 가지고 또 다른 질문이 있습니다. 익명 클래스의 인스턴스를 만들 때 type 매개 변수 클래스 정보를 사용할 수 있습니다. 이 방법으로 만든 여러 인스턴스가 다른 익명 클래스 될 것입니다, 그리고 그 문제의 경우 새에 대한 호출을 대체하는 복제를 기반으로 createNew() 함수와 클래스 A_String_Factory을 할 수 있습니다

class A<T> 
{ 
    A() 
    { 
     java.lang.reflect.ParameterizedType parameterizedType = (java.lang.reflect.ParameterizedType) (this.getClass().getGenericSuperclass()); 
     System.out.println(parameterizedType.getActualTypeArguments()[0]); 
    } 
} 

public class Example { 
public static void main(String[] args) { 
    A<String> anonymous = new A<String>() {}; // prints java.lang.String 
} 
} 

참고.