2013-05-22 11 views
5

Ich habe generische Klasse:Java erstellen Objekte generischen Typ mit unbekannter in Zusammenstellungsart Parameter

class Field<T> { } 

Und eine andere Klasse (dessen Typen ich weiß nur zur Laufzeit) mit vielen erhaltenen Methoden zum Beispiel:

class A{ 
     public Date getDate(); 
     public String getName(); 
     public Integer getNumber(); 
    } 

Ich möchte Instanzen der Klasse Field für alle Get-Methoden erstellen, mit T entspricht, um Typ dieser get Methoden zurückzugeben. Für dieses Beispiel Field<Date>, Field<String>, Field<Integer>.

Kann jemand helfen?

+2

Wenn Sie diese werden durch Reflexion tun, und zur Laufzeit, der generische Typ nicht egal. Sie können es auch ohne den generischen Parameter tun. –

+0

Ich verstehe nicht, was Sie versuchen zu tun. Schreiben Sie ein vollständiges Codebeispiel, auch wenn es nicht kompiliert wird, das veranschaulicht, was Sie erreichen möchten. – erickson

+0

Die Reflektion ist für diesen Anwendungsfall nicht geeignet. Erwägen Sie die Verwendung von Introspection, die Methoden direkt verfügbar machen, um die Getter zu erhalten. –

Antwort

2

Sie verwenden Reflection normalerweise für Dinge, die Sie nur zur Laufzeit kennen. Generika-Informationen werden zur Kompilierzeit gelöscht. Obwohl es Fälle gibt, in denen Sie die beiden mischen können, ist es nicht üblich.

Ich möchte Instanzen der Klasse Feld für alle Get-Methoden erstellen, mit T gleich, um Typ dieser Get-Methoden zurückzugeben. Für dieses Beispiel Feld, Feld, Feld.

Um Ihre Frage zu beantworten, wörtlich:

Field<Date> dateField = new Field<Date>(); 
Field<String> nameField = new Field<String>(); 
Field<Integer> numberField = new Field<Integer>(); 
1

Ich glaube nicht, dass Sie generische Arten von Field in diesem Fall erstellen können, da Generika zur Kompilierzeit überprüft werden, während Sie nur die Rückgabetypen der deklarierten Methoden der Klasse A (über Reflektion) erhalten können Laufzeit.

+0

die einzige Möglichkeit, eine Liste für unbekannte Klassen zu machen ist Liste , aber das wird nicht viel helfen. – pad

1

die Getter zu erhalten, betrachten Selbstbeobachtung mit eher als Reflexion: Es ist für diesen Zweck bestimmt ist!

Hier ist ein Code, um die Getter automatisch zu erhalten. Vorsicht, du bekommst auch "getClass()" Getter!

for(PropertyDescriptor descriptor :Introspector.getBeanInfo(A.class).getPropertyDescriptors()){ 
    System.out.println("Getter method :" + descriptor.getReadMethod()); 
    System.out.println("Return type : " + descriptor.getReadMethod().getReturnType()); 
    Class<?> c=descriptor.getReadMethod().getReturnType(); 
} 

}

Ausgang:

Getter method :public final native java.lang.Class java.lang.Object.getClass() 
Return type : class java.lang.Class 
Getter method :public java.util.Date A.getDate() 
Return type : class java.util.Date 
Getter method :public java.lang.String A.getName() 
Return type : class java.lang.String 
Getter method :public java.lang.Integer A.getNumber() 
Return type : class java.lang.Integer 

Dann können Sie leicht ein Feld für jede dieser Getter erstellen. Für den generischen Typen, ist es nicht wirklich Sinn zur Laufzeit machen, aber es ist immer noch möglich, dies in einem Code-Generator zu verwenden ...

+0

Oder verwenden Sie Commons Beanutils. –

2
class Field<T> { 
    T value; 
    Field(T value) {this.value = value;} 
} 


class A{ 
    Date date; 
    public Field<Date> getDate() { 
     return new Field<Date>(date); 
    } 

    //etc.... 
} 

Denken Sie an Generika als Compiler Anmerkungen anstelle der tatsächlichen Laufzeittyp überprüft. Der kompilierte Code hat einfach statische Umwandlungen und führt überhaupt keine generische Typüberprüfung durch. Die Generics-Funktion wurde einfach an den Compiler angehängt, um die Laufzeitkompatibilität mit älteren JVMs zu gewährleisten, und zwar mit dem, was Sun als "Type Erasure" bezeichnete. Hier sind einige gute Lektüre über sie:

http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

Verwandte Themen