Problem mit Java Generics

Hauke

Mitglied
Hallo

Ich habe eine Klasse (Vektor) erst einmal ohne Generics Programmirt (intern double), jetzt Wollte ich die Klasse mit Generics Ausstatten. Da stoße ich auf ein paar Probleme. (so gut kenne ich mich bei der Entwicklung noch nicht aus, nur beim Benutzen)

Ersteinmal der Klassen Rumpf und zwei Feldern.

Java:
public class Vektor<T extends Number> implements Cloneable {
	public T[] daten;
	public final int length;
}

Zu dem „Haupt“ Konstruktoren:
Java:
	@SuppressWarnings("unchecked")
	public Vektor(int n){
		Class<?> h = Number.class;
		daten = (T[]) Array.newInstance( h, n );
		
		//T[] array = (T[])new Object[n];     
        //daten = array;  
		
		length = n;
	}
Erstellt man ein Array des Types T auch so wie bei mir im Code?
Wenn ich den einzelnen Elementen des Arrays etwas zuweise muss ich sie wohl jetzt Clonen?
Jetzt eine Frage zum Rechnen, was allgemein so aussieht:
Java:
	@SuppressWarnings("unchecked")
	public static <T extends Number> Vektor<T> operation(Vektor<T> a, Vektor<T> b, Operation op)
	{
		if (a.length != b.length){
			throw new UnequalLengthException();
		}
		int n= a.length;
		Vektor<T> ret = new Vektor<T>(n);
		
		for(int i = 0;i < n;i++){
			Double d=null;
			switch (op){
			case ADD:
				 d= (Double) (a.daten[i].doubleValue() + b.daten[i].doubleValue());
				 break;
			case MUL:
				d =  a.daten[i].doubleValue() *b.daten[i].doubleValue();
				break;
			}
			ret.daten[i] = (T) d;
			
		}
		return ret;
	}
(So ist das noch nicht richtig)
Entweder wie kann ich ein „instanceof“ machen oder schöner gibt es eine Möglichkeit mit „Number„ allgemein zu rechnen?
 
die einfachste Variante für das Array ist
> new Object[n]

wenn du schon nicht genau den aktuellen Typ T hast, dann brauchst du Number fürs Array auch nicht unbedingt,
na ok, ist schon denkbar bei manchen Verwendungen, wenn man das Array komplett herausholt

> Wenn ich den einzelnen Elementen des Arrays etwas zuweise muss ich sie wohl jetzt Clonen?
nicht zwingend, und da Number normalerweise unveränderbar wie Strings sind, eigentlich gar nicht nötig


-----------

Java:
            case ADD:
                 d= (Double) (a.daten[i].doubleValue() + b.daten[i].doubleValue());
                 break;
            case MUL:
                d =  a.daten[i].doubleValue() *b.daten[i].doubleValue();
willst du noch 5x weiter 'a.daten.doubleValue()' usw. schreiben?
sieht ja jetzt schon schlimm aus, besser:
Java:
double da = ..;
double db = ..;

            case ADD:
                 d= (Double) (da + db);
                 break;
            case MUL:
                d =  da *db;
usw., der Cast auf Double ist wohl auch nicht nötig?

wenigstens hattest du bisher schon d als Ergebnis und nicht ständig noch ret.daten..
 
@SlaterB: Ich hoff' das "normalerweise" spielt ausschliesslich auf die in der Standard-VM vorhandenen Number-Klassen an. Ansonsten ist Number nämlich abstract und jeder kann's verwenden wie er will, also auch, Gott beware, mutable Numbers erzeugen.

Das Datenarray des Vectors darf auf jedenfall vom Typ [c]Number[][/c] sein nur rechnen kann man damit afaik leider auch nicht.
 
so meinte ich das mit normalerweise, ja,

ach ja, selbst new Number[n] kann man direkt hinschreiben, bei fester Klasse braucht es kein 'Array.newInstance'
 
OK, bisschen habe ich mir das schon gedacht, nur währe dann gut zu Prüfen, welcher Type Double, Float, BigDecimal etc. ist damit auch gerechnet werden kann. Ich will ja nicht immer nach Double Casten sondern, wenn ich z. B. BigDecimal habe damit rechnen, das ist meine eigentliche Fragen (
Code:
if(T isInstanceOf BigDecimal)
) so etwas in der Richtung.
 
T kannst du nicht testen, nein, entweder muss Class<T> anfangs mit übergeben werden oder ein Objekt,
am Anfang ein Dummy bzw. später einen der Werte anschauen

schön wird so eine Verzweigung kaum, eine Alternative kann ich aber auch nicht wirklich nennen
 
Das übergeben eines Dummies ist beim Rechnen ja gar nicht so schwer. Ich habe mal spasseshalber mit 'ner Number-Kompatiblen Lib angefangen, ein Auszug daraus sieht etwa so aus:
Java:
public static <T extends Number> T sqrt(T i)
{
	return convert(i, BigDecimalMath.sqrt(toBigDecimal(i)));
}

public static <T extends Number> T pow(T x, Number y)
{
	return convert(x, BigDecimalMath.pow(toBigDecimal(x), toBigDecimal(y)));
}

@SuppressWarnings("unchecked")
public static <T extends Number> T convert(T out, Number in)
{
	return (T) ((out instanceof Double)? toDouble(in) :
		(out instanceof Float)? toFloat(in) :
			(out instanceof Long)? toLong(in) :
				(out instanceof Integer)? toInteger(in) :
					(out instanceof Short)? toShort(in) :
						(out instanceof Byte)? toByte(in) :
							(out instanceof BigDecimal)? toBigDecimal(in) :
								(out instanceof BigInteger)? toBigInteger(in) :
									in);
}
Die einzelnen to-Methoden sind ein Klacks, im Gegensatz zu den BigDecimal-Methoden "pow" und "sqrt" aus dem Beispiel.
 

Zurück
Oben