# Java Generics - Wie komme ich an die <T>.class?



## timomeinen (12. Okt 2006)

Hallo Javaraner,

ich verzweifele ein wenig an den Generics. Vielleicht habe ich ja nur ein Brett vor dem Kopf und jmd. kann mir helfen:

Ich habe eine Klasse mit Generics. In dieser Klasse möchte ich per Reflection eine Methode aufrufen. Um an das Method-Objekt zu gelangen brauche ich die Class-Klasse dieser Klasse. Wie komme ich an das Class-Objekt?

Hier das Beispiel:

```
public class StandardTableModel<T> extends AbstractTableModel {

// Hierin sollen alle Elemente der Tabelle stehen
protected ArrayList<T> elements;


public Object getValueAt(int row, int column) {
   Method method = <T>.getMethod("get" + methods[column]);
            Object returnValue = method.invoke(elements.get(row), (Object[]) null);
            return returnValue;
    }
}
```

Die Stelle *<T>.getMethod* kann natürlich nicht klappen, aber ich habe es geschrieben, damit ihr seht an welcher Stelle mein Problem ist. Ich bräuchte also eine Art T.getClass() oder T.class.

Danke schön
Timo Meinen
timomeinen@gmail.com


----------



## moormaster (12. Okt 2006)

Geht das nicht?


```
<T>.getClass()
```


----------



## Roar (12. Okt 2006)

zur laufzeit ist T nicht bekannt - wie auch schon in mehreren anderen threads hier im forum erklärt.
wenn T eine liste sein soll schreibe
class StandardTableModel<T extends List>
...
return elements.get(row).get(column);


----------



## timomeinen (12. Okt 2006)

Es kommt leider eine "illegal start of expression" :


```
StandardTableModel.java:78: illegal start of expression
            Method method = <T>.getClass().getMethod("set" + methods[column]);
1 error
```


----------



## timomeinen (12. Okt 2006)

Roar hat gesagt.:
			
		

> wenn T eine liste sein soll schreibe



Danke für den Tipp, aber T soll eine JavaBean sein aus denen die Werte der Tabelle ausgelesen werden können. Daher der Umweg über Reflection.


----------



## Roar (12. Okt 2006)

warum dann nich gleich: ArrayList<MeineJavaBean> oder <T extends OberJavaBean>


----------



## Campino (12. Okt 2006)

kannst du nicht "einObjectdasinstancevonTist".getClass() aufrufen? In der ArrayList müssen doch welche davon sein...


----------



## timomeinen (12. Okt 2006)

Roar hat gesagt.:
			
		

> warum dann nich gleich: ArrayList<MeineJavaBean> oder <T extends OberJavaBean>



Es soll ein TabellenModell fuer unterschiedliche JavaBeans sein. Ein GenericTableModel.  

Aber wie kaeme ich denn dann mit <T extends OberJavaBean> an das Class-Objekt?

Danke fuer die Diskussion
Timo


----------



## Roar (12. Okt 2006)

nochmal: du kannst zur laufzeit nicht wissen von welchem typ das objekt ist.

an das Class objekt von einer bestimmten instanz kommst du ganz normal wie immer:
elements.get(row).getClass().getMethod....

nebenbei: wenn du für T eh keinen gemeinsamen nenner hast, kannst du dir die generics auch schenken (falls du sie nicht weiter verwendest in der klasse)


----------



## SlaterB (12. Okt 2006)

Method method = elements.get(0).getClass().getMethod("get" + methods[column]);


----------



## byte (12. Okt 2006)

Das ist die fundamentale Einschränkung bei den Java Generics, dass das T zur Laufzeit nicht mehr bekannt ist. Das sollte man begriffen haben, bevor man mit Generics arbeitet, denn sonst wird man ständig diesen "Hä??" Effekt haben. 

Also: Das T wird beim Kompilieren erased. Im Prinzip steht also zur Laufzeit überall statt T ein Object.


----------



## timomeinen (12. Okt 2006)

Campino hat gesagt.:
			
		

> kannst du nicht "einObjectdasinstancevonTist".getClass() aufrufen? In der ArrayList müssen doch welche davon sein...


Sehr gute Idee. Damit funktioniert es. Das ist schon mal ein guter Workaround. Vielen Dank.

Dennoch: Kann ich bei der Verwendung der Generics mit <T>, wie in diesem Fall, nicht an das Class-Objekt kommen? Muss ich immer ein instanziiertes Objekt haben?


----------



## Guest (12. Okt 2006)

Wie wär's mit Initialisierungdes Zugriffs auf die Felder der Zeilen zur Laufzeit?
	
	
	
	





```
public class StandardTableModel<T> extends AbstractTableModel
{
   private String columns[];

   public StandardTableModel(String columns[])
   {
      super();
      if(columns == null) 
         throw new IllegalArgumentException("Der Parameter 'columns' darf nicht null sein!");
      this.columns = columns;
   }

   ...

   public Object getValueAt(int row, int column)
   {
      if(row >= elements.size())
         throw new IllegalArgumentException("Zeile " + row + " gibt's nicht!");
      if(column >= columns.length)
         throw new IllegalArgumentException("Spalte " + column + " gibt's nicht!");

      T rowModel = elements.get(row);
      return getRowAccess(rowModel).getValue(rowModel, column);
   }
   
   protected RowAccess getRowAccess(T rowModel)
   {
      if(rowAccess == null)
      {
         rowAccess = new RowAccess(rowModel.getClass(), columns);
      }
      return rowAccess;
   }

   ...
```
RowAccess analysiert die Klasse im Konstruktor und bietet eine
Methode zum Zugriff auf die entsprechenden Felder an.

Ein Problem bleibt dir aber getRowCount(), wenn noch nix drin steht.
Du könntest dein Model mit einem String-Array initialisieren, wo die
Namen der Felder aufgelistet sind (wie oben gezeigt), die gelesen bzw. 
in der Tabelle angezeigt werden.


----------



## Campino (12. Okt 2006)

timomeinen hat gesagt.:
			
		

> Campino hat gesagt.:
> 
> 
> 
> ...



Ja, du musst immer ein Instanziertes Objekt haben, weil die Generics zur Laufzeit nicht existieren, dass <T> wird beim compilieren beseitigt.


----------

