2014-02-25 3 views
1

아래의 Crud 오브젝트 코드에서 보면, T 타입의 Field 오브젝트 배열이 예상됩니다. 실제로 표시되는 것은 Object 유형의 Field 오브젝트 빈 배열입니다. 내 테스트 클래스는 Timezone이라고합니다. 그래서 Crud 객체를 인스턴스화하면 다음과 같이 보입니다.일반 오브젝트의 유형에 액세스하려면 어떻게해야합니까?

Crud<Timezone> tz = new Crud<Timezone>(); 

하지만 제가 말한 것처럼 이것이 작동하지 않습니다. 도움말 감사.

import java.util.*; 
import java.lang.reflect.*; 
public class Crud<T> { 

    public T getInstance() 
    { 
     @SuppressWarnings("unchecked") 
     T object = (T) new Object(); 
     return object; 
    } 

    public ArrayList<String> getMembers() { 
     ArrayList<String> retval = new ArrayList<String>(); 
     try { 
      T object = this.getInstance(); 
      Field[] fields = object.getClass().getDeclaredFields(); //Always empty 
      for (Field field : fields) { 
       retval.add(field.getName()); 
      } 
     } catch (Exception e) { 
      System.out.println(e); 
     } 

     return retval; 
    } 

} 
+0

그들이'Object's, 당신은'새 개체() 한;의' – m0skit0

+0

가능한 중복을 [어떻게 런타임에 제네릭 형식을 얻는 방법? ] (http : // stackoverflow.com/questions/3941384/how-to-get-the-generic-type-at-runtime) –

+0

당신이 경고하고 있다는 경고 : 여기서는 유용합니다. – Radiodef

답변

0

아마도 getDeclaredFields()은 시간대 클래스 인 표준 시간대에 구현해야합니다.

public class Crud<T> { 

    private final Class<T> mClass; 

    public Crud(Class<T> tClass) 
    { 
     mClass = tClass; 
    } 

    public T getInstance() throws Exception 
    { 
     T object = mClass.newInstance(); 
     return object; 
    } 

    ... 
} 

을 그리고 우리는 다음과 같이 사용할 수 있습니다 :

+0

나는 당신의 대답을 정말로 이해하지 못합니다. 그리고'getDeclaredFields()'를 구현할 필요가 없다. 모든 클래스 객체는이 메소드를 가진다. – m0skit0

0

우리는과 같이 일반 클래스를 정의 할 수 있습니다

try 
{ 
    Date tDate = new Crud<Date>(Date.class).getInstance(); 
    System.out.println("Date: " + tDate); 
} 
catch(Exception e) 
{ 
    System.out.println("Error: " + e); 
} 

출력 : Date: Mon Feb 24 21:00:04 PST 2014

+1

'tClass'를 무언가로 초기화하지 않는 한 이것은 널 포인터 예외입니다. 언제 그리고 어떻게 초기화 할 계획입니까? – ajb

+0

@ajb 당신은 완전히 옳습니다. 새로운 코드를 테스트했는데 수정해야합니다. –

1

것은 당신이 원하는 것은 포장되는 경우 인스턴스를 얻고 필드를 확보하면 generics가 필요하지 않습니다. Object을 기본 클래스로 사용하여 랩퍼에 모든 종류의 오브젝트를 허용 할 수 있습니다. 예를

public class Crud { 

    private final Object object; 

    public Crud(final Object someObject) { 
     this.object = someObject; 
    } 

    public ArrayList<String> getMembers() { 
     ArrayList<String> retval = new ArrayList<String>(); 
     try { 
      Field[] fields = this.object.getClass().getDeclaredFields(); 
      for (Field field : fields) { 
       retval.add(field.getName()); 
      } 
     } catch (Exception e) { 
      System.out.println(e); 
     } 

     return retval; 
    } 

} 

를 들어 다음 당신은 당신이 이런 건 할 수 없어, 심지어 제네릭없이

Crud tz = new Crud(new Timezone()); 
2

을 수행

Timezone object = (Timezone) new Object(); 

new Object() 객체를 생성합니다을 실행시의 형태Object입니다 . 여기에는 Object의 모든 필드와 메소드가 있지만 다른 필드는 없습니다. Object이 만들어지면 캐스트를 사용하여 개체를 마술로 다른 유형으로 변환 할 수 없습니다. 그 모든 새로운 필드와 방법을 추가하는 것입니다 Timezone 가지고 있고, 자바는 그렇게 할 수 없습니다.

그래서이 가능 중 하나가 작동 할 수 없습니다

T object = (T) new Object(); 

불행하게도, 자바 못하게 이렇게 중 하나 때문에 "유형 삭제"의

T object = new T(); 

. 이 문제를 해결하기위한 아이디어는 Create instance of generic type in Java?을 참조하십시오.

2

아니요, type erasure으로 인해 런타임에 유형에 액세스 할 수 없습니다.

그러나 제네릭 형식의 인스턴스를 만드는 문제를 해결할 수있는 패턴이 있습니다. 생성자에 유형 토큰를 통과해야합니다 : 물론

public class Crud<T> { 
    private Class<T> clazz; 
    public Crud(Class<T> clazz) { 
     this.clazz = clazz; 
    } 

    public T getInstance() { 
     return clazz.newInstance(); 
    } 
관련 문제