Generics: Typparameter als Klasse zurückliefern

javabar

Mitglied
Hallo!

Ich habe eine Klasse Column mit Typparameter (T).
Ist es möglich, die Klasse des übergebenen Typs in einer Methode zurückzuliefern?

Java:
    public abstract class Column<T> {
        private String name;

        public Column(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        // Klasse ist abstrakt, es muss eine Methode implementiert werden,
        // die einen Wert vom Typ T zurückliefert
        public abstract T getValue(Object object);

        // soll die Klasse von T zurückliefern
        public Class getValueClass() {
             // return T.class;
        }

    }

Grüße

Egon
 
nur wenn du noch explizit das passende Class objekt der Klasse mitteilst
Java:
public abstract class Column<T> {
        private String name;
        private Class<? extends T> theClass;
 
        public Column(String name, Class<? extends T> theClass) {
            this.name = name;
            this.theClass = theClass;
        }

        public Class<? extends T> getValueClass() {
             return theClass;
        }
}
 
Danke, das hat weiter geholfen, naja ganz sauber ist die Lösung nicht.

Der Sinn des Ganzen ist, ich arbeite an einer Klasse, die es erleichtern soll, Objektlisten vom Typ List<T> in Swing-Tabellen darzustellen.

Java:
package mypackage;

import java.util.ArrayList;
import java.util.List;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class DataObjectTable<T> extends JTable {

    private List<T> list;
    private List<AbstractColumn> columns;
    private Model model;
    
    public DataObjectTable(List<T> list) {
        this.list = list;
        columns = new ArrayList<AbstractColumn>();
        model = new Model();
        setModel(model);
    }

    public void addColumn(AbstractColumn c) {
        columns.add(c);
        model.fireTableStructureChanged();
    }

    public List<AbstractColumn> getColumns() {
        return columns;
    }

    class Model extends AbstractTableModel {
        @Override
        public int getRowCount() {
            return list.size();
        }
        @Override
        public int getColumnCount() {
            return columns.size();
        }
        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return columns.get(columnIndex).getValue(list.get(rowIndex));
        }
        @Override
        public String getColumnName(int column) {
            return columns.get(column).getName();
        }   
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return columns.get(columnIndex).getColumnClass();
        }
    }

    public abstract class AbstractColumn<U> {

        private String name;
        private Class<? extends U> theClass;

        public AbstractColumn(String name, Class<? extends U> theClass) {
            this.name = name;
            this.theClass = theClass;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Class<? extends U> getColumnClass() {
            return theClass;
        }
        public abstract U getValue(T object);
    }
}

Statt an mehreren Stellen mit switch-case zu arbeiten, lässt sich eine Spalte für ein Property oder einem berechneten Wert mit

Java:
addColumn(new AbstractColumn<Long>("Artikelnummer", Long.class) {
    @Override
    public Long getValue(Auftrag auftrag) {
        return auftrag.getArtikelnummer();
    }
});

Der Typ des Spaltenwertes wird in AbstractTableModel.getColumnClass() benötigt. Ganz perfekt ist die Lösung nicht, und wenn "theClass" eine abgeleitete Klasse vom Typparameter ist, dann führt das fast zwangsläufig zu einer java.lang.ClassCastException.

Grüße

Egon
 

Zurück
Oben