Warnungsfreie Verwendung von Generics

T

Throwable

Gast
Hallo allerseits,

ich habe da ein kleinen Codeschnipsel, der Verwendung von Generics macht, den ich aber nicht warnungs- bzw. fehlerfrei bekomme. Ich hab den Code aufs Nötigste reduziert. Sind trotz allem noch 60 Zeilen, aber nicht abschrecken lassen: Die Logik ist sehr simpel.

Kurz um was es geht: Es gibt eine Klasse Component. Aus dieser werden Tupel aufgebaut. Ein Tupel ist einfach ein Array aus Components. Und diese Tupel sollen verglichen werden können. Aber seht selbst:

Java:
public class Demo {
    
    public Demo() {
        Component<?>[] tuple1 = new Component<?>[] {
            new Component<Integer>(1),
            new Component<Float>(1.0f),
            new Component<Double>(1.0),
            new Component<Character>('L'),
            new Component<String>("Lorem ispum dolor sit amet"),
        };
        Component<?>[] tuple2 = new Component<?>[] {
            new Component<Integer>(1),
            new Component<Float>(1.0f),
            new Component<Double>(1.0),
            new Component<Character>('L'),
            new Component<String>("Lorem ispum dolor sit amet"),
        };
        if (isGreaterThan(tuple1, tuple2)) {
            System.out.println("Tuple1 is greater than tuple2.");
        }
    }
    
    public static void main(String args[]) {
        new Demo();
    }
    
    private boolean isGreaterThan(Component<?>[] tuple1, Component<?>[] tuple2) {
        if (tuple1.length < tuple2.length) {
            return false;
        } else if (tuple1.length > tuple2.length) {
            return true;
        } else {
            for (int i = 0; i < tuple1.length; i++) {
                if (tuple1[i].compareTo(tuple2[i]) < 1) {
                    return false;
                }
            }
            return true;
        }
    }
}

class Component<T extends Comparable<? super T>> implements Comparable<Component<?>> {
    
    private T value;
    
    public Component(T value) {
        super();
        this.value = value;
    }
    
    public T getValue() {
        return value;
    }
    
    @Override
    public int compareTo(Component<?> o) {
        return this.getValue().compareTo(o.getValue());
    }
}

So gibt es einen Fehler in der vorletzten Zeile, der dadurch gelöst werden kann, dass ich bei der Deklaration der Klasse Component nur <T extends Comparable> schreibe. Dann gibt es jedoch wieder eine Warnung in der Zeile der Klassendeklaration, da Comparable nicht parametrisiert ist. Ich drehe mich schon seit mehreren Stunden im Kreis und komme nicht auf die Lösung. Ist es überhaupt möglichen, diesen Code warnungsfrei zu bekommen? Und wenn nein, wie sähe eine Alternative aus?
 

turtle

Top Contributor
Java:
public class Demo {

	public Demo() {
		Component<?>[] tuple1 = new Component<?>[] { new Component<Integer>(1),
				new Component<Float>(1.0f), new Component<Double>(1.0),
				new Component<Character>('L'),
				new Component<String>("Lorem ispum dolor sit amet"), };
		Component<?>[] tuple2 = new Component<?>[] { new Component<Integer>(1),
				new Component<Float>(1.0f), new Component<Double>(1.0),
				new Component<Character>('L'),
				new Component<String>("Lorem ispum dolor sit amet"), };
		if (isGreaterThan(tuple1, tuple2)) {
			System.out.println("Tuple1 is greater than tuple2.");
		} else
			System.out.println("Tuple1 is not greater than tuple2.");
	}

	public static void main(String args[]) {
		new Demo();
	}

	private boolean isGreaterThan(Component<?>[] tuple1, Component<?>[] tuple2) {
		if (tuple1.length < tuple2.length) {
			return false;
		} else if (tuple1.length > tuple2.length) {
			return true;
		} else {
			for (int i = 0; i < tuple1.length; i++) {
				if (tuple1[i].compareTo(tuple2[i]) < 1) {
					return false;
				}
			}
			return true;
		}
	}
}

class Component<T extends Comparable<T>>  {

	private T value;

	public Component(T value) {
		super();
		this.value = value;
	}

	public int compareTo(Component<?> component) {
		return this.getValue().compareTo((T) component.getValue());
	}

	public T getValue() {
		return value;
	}

}
 
T

Throwable

Gast
Dann gibt es allerdings leider eine Unchecked-Cast-Warning in der Zeile mit dem Type Cast. Wirklich was gewonnen hat man also leider nicht...
 

Marco13

Top Contributor
Das ist nicht type safe. Und darauf weist er hin. Nicht mehr und nicht weniger. Wenn man zwei Tuples erstellt
Java:
tuple1 = new Component<?>[] { new Component<Integer>(1) };
tuple2 = new Component<?>[] { new Component<String>("This is a test") };
Dann versucht er irgendwann irgendwo einen String und einen Integer zu vergleichen. Die Objekte sind zwar beide "Comparable", aber nicht mutually comparable. Egal wie man's macht: Es macht keinen Sinn. Theoretisch gibt's nur die Möglichkeit, dort ein [c]suppressWarnings("unchecked")[/c] hinzuschreiben, oder die Typen eines Tupels mitzuschleifen. Letzteres ist aber prinzipbedingt nicht praktikabel, weil man ja nicht weiß, wie viele verschiedene Typen in einem Tupel stecken können.
 

Landei

Top Contributor

Nun ja, gehen tut das schon, nur sieht es nicht hypsch aus:

Java:
package somePackage;

public abstract class Tuple<A extends Tuple<A>> {
    
    public abstract <X> Cons<X, A> and(X x);
    
    public static class Nil extends Tuple<Nil> {
        @Override
        public <X> Cons<X, Nil> and(X x) {
            return new Cons<X, Nil>(x, this);
        }
    }

    public static class Cons<E, L extends Tuple<L>> extends Tuple<Cons<E,L>> {
        public final E value;
        public final L next;
        private Cons(E e, L l) {
            value = e;
            next = l;
        }

        @Override
        public <X> Cons<X, Cons<E, L>> and(X x) {
            return new Cons<X, Cons<E, L>>(x, this);
        }
    } 
    
    public static <Z> Cons<Z, Nil> of(Z z){
        return new Nil().and(z);
    }
}

Java:
import java.util.Date;
import static somePackage.Tuple.*;

public class TupleTest {
    public static void main(String[] args) {
        Cons<Integer,Cons<String,Cons<Date,Nil>>> tuple = Tuple.of(new Date()).and("bla").and(1);
        int x = tuple.value;
        String y = tuple.next.value;
        Date z = tuple.next.next.value;
        System.out.printf("%d %s %s%n",x,y,z);
       //--> 1 bla Sun Jul 31 18:53:46 CEST 2011
    }
}

Und alles beliebig lang, typsicher und ohne Warnungen. Natürlich möchte man solche Typen am liebsten bei den Flusen hinter dem Kühlschrank verstecken, aber prinzipiell geht es. Eventuell lässt sich das mit etwas Finetuning auch noch ein wenig verbessern (insbesonders die "rückwärtse" Initialisierung), meine Implementierung ist hier wirklich minimal. Das ist übrigens ein Argument dafür, dass die Diamant-Operator-Typinferenz genau in die falsche Richtung (nämlich rechts) geht: Wäre es andersherum, könnte man [c]Cons<> tuple =...[/c] schreiben.

Wenn ich mir deinen Link anschaue, hast du schon in eine ganz ähnliche Richtung gedacht...

Der obige Wahnsinn ist übrigens nicht auf meinem eigenen Mist gewachsen, ich habe mich frech bei HList (Functional Java 3.0) bedient.
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Ja, sieht recht ähnlich zu meinen Gehirnkrämpfen von damals aus :D

Aber irgendwie gibt's ja nicht viele Alternativen: Entweder, man hat KEINE Typsicherheit, dann schreibt man eben
var list = { "Hallo", 123, new Date("12.3.1956") }
oder man WILL die Typsicherheit, dann muss man die Typen auch hinschreiben. Natürlich wäre
List<String, Integer, Date> list = ....
schöner als
T<String, T<Integer, T<Date>>> list = ....
aber böswillig könnte man das dann doch nur "syntaktischen Zucker" nennen.
 
T

Throwable

Gast
Okay, schade, dass man den Compiler nicht "endgültig" besänftigen kann. Aber ich sehe ein, dass es schon in der Theorie eigentlich zu einer Warnung wegen mangelnder Typsicherheit kommen muss. Und dann lieber Warnung, als die "Lösung" von Landei. ;) Das ist dann doch etwas zu verkompliziert. Danke an alle.
 

Landei

Top Contributor
Wenn ich mich recht entsinne, gab es einmal eine Bibliothek, die im Hintergrund so ähnlich gearbeitet hat (also prinzipiell beliebig lange Tuple zugelassen hat), aber für die normale Arbeit darauf aufbauend eine Facade mit [c]Pair<A,B>[/c], [c]Triple<A,B,C>[/c] u.s.w. bereitgestellt hat. Finde sie leider nicht mehr...
 

Marco13

Top Contributor
Naja, der letzte Post sollte nur schon andeuten, dass mehr als 10 Dimensionen ohnehin schon fragwürdig sind. Selbst WENN dann die "Verkürzte" Schreibweise möglich wäre, wäre sowas wie
List<Integer, String, Date, Component, List<Integer>, Float, Double, Float, Integer, Set<String>> list = ...
ja ziemlich :autsch:
War das dann irgendeine Bibliothek, die einen "Pre-Compiling"-Schritt eingebaut hat?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Z JNA Cpp-DLL String Verwendung Allgemeine Java-Themen 2
M WSDL: Doppelte Typenames (Keine Verwendung möglich) Allgemeine Java-Themen 5
F Klassen Verwendung abstrakter Klassen Allgemeine Java-Themen 9
K Saubere Verwendung von Generic Types Allgemeine Java-Themen 7
D Verwendung von Selenium Allgemeine Java-Themen 2
P ClassCastException bei Verwendung eines Interfaces Allgemeine Java-Themen 7
M Fehler bei Verwendung von TexturePaint Allgemeine Java-Themen 16
S OOP Apache Commons Math - Verwendung von Genetics - Wie werden Daten in Chromosomen gespeichert? Allgemeine Java-Themen 4
M Verwendung der Cipher von gnu crypto (Serpent) Allgemeine Java-Themen 3
B Verwendung von Packages im Java Code Allgemeine Java-Themen 10
P Richtige Verwendung eines Timers Allgemeine Java-Themen 8
M Problem bei der Verwendung von AES Allgemeine Java-Themen 2
J Port verwendung Allgemeine Java-Themen 13
M Verwendung von unchecked exceptions & bereits vorhandenen exceptions was priorisieren Allgemeine Java-Themen 3
X Wie 'teuer' ist die Verwendung des Stack Trace ? Allgemeine Java-Themen 8
Final_Striker Exceptionhandling: Richtige Verwendung des Try/Catch Blocks Allgemeine Java-Themen 14
W Verwendung von byte Allgemeine Java-Themen 9
L Verwendung? Allgemeine Java-Themen 2
D Fehlerhafte Thread Verwendung beim arbeiten mit Sockets Allgemeine Java-Themen 6
N allg. Frage zur Verwendung von this Allgemeine Java-Themen 3
G Verwendung von DataInputStream und URL Allgemeine Java-Themen 2
C Seltsame Konstanten (und Verwendung) Allgemeine Java-Themen 15
X Exception bei Verwendung von systray4j Allgemeine Java-Themen 5
J Best Practice Generics mit Enum Allgemeine Java-Themen 3
H Kombination Interface und Abstrakte Klasse bei Generics Allgemeine Java-Themen 3
Zeppi Cast Object in Generics Allgemeine Java-Themen 4
P Generics und Arrays Allgemeine Java-Themen 6
M Generics / Typen Allgemeine Java-Themen 1
Kirby.exe InsertionSort mit Generics Allgemeine Java-Themen 33
Kirby.exe Vererbung bei Generics Allgemeine Java-Themen 7
H Klarnamen etc... (von Wie Generics lernen?) Allgemeine Java-Themen 26
D Wie Generics lernen? Allgemeine Java-Themen 26
L Compiler-Fehler Generics beim Anhängen von Predicates Allgemeine Java-Themen 1
W Vererbung Generics - mal wieder die verhaßte Rückwärtskompatibilität Allgemeine Java-Themen 2
S Verstaendnisfrage Generics Allgemeine Java-Themen 19
W Generics + Vererbung Allgemeine Java-Themen 47
I Methoden Generics-Methode Allgemeine Java-Themen 3
D Mit Generics arbeiten - Übungsaufgabe Allgemeine Java-Themen 3
K Factory Pattern: Mit Generics umgehen Allgemeine Java-Themen 6
G Generics Allgemeine Java-Themen 31
perlenfischer1984 Liste mit generics zurück liefern Allgemeine Java-Themen 8
Hacer Generics & Collections Allgemeine Java-Themen 8
Neumi5694 Interface Generics für Enum-Filterung verwenden Allgemeine Java-Themen 5
H Collector Generics Problem (incl. Stream & Lambda) Allgemeine Java-Themen 4
C Gemeinsame Oberklasse zweier Generics Allgemeine Java-Themen 10
erdmann Datentypen Methodendeklaration mit Generics Allgemeine Java-Themen 2
Z Datentypen Verschachtelte Generics Allgemeine Java-Themen 1
Neumi5694 Datentypen Generics Allgemeine Java-Themen 5
S Mit Generics Klasse erstellen die selbst T erweitert..? Allgemeine Java-Themen 4
Tarrew Generics - Type erasure Allgemeine Java-Themen 5
N Problem mit Generics und Interface Allgemeine Java-Themen 4
H Generics als Parameter Allgemeine Java-Themen 1
kaoZ Generics und Vererbung Allgemeine Java-Themen 3
A Datentypen Generics: Wie am besten auf Typparameter zugreifen Allgemeine Java-Themen 2
C Generics Objekt in ArrayList Allgemeine Java-Themen 2
vandread Kleine Generics Aufgabe aus einer Prüfung... wie ist das gemeint? Allgemeine Java-Themen 6
G Generics sind zu streng - oder ich zu naiv? Allgemeine Java-Themen 3
G Verschachtelte Generics Allgemeine Java-Themen 2
O Generics Allgemeine Java-Themen 42
M Problem mit Generics Allgemeine Java-Themen 10
M Generics (bounded wildcards statt Interface Bezeichnern) -- Sinn oder Unsinn? Allgemeine Java-Themen 2
darekkay Generics: Wildcard und Object Allgemeine Java-Themen 5
H Collections Generics und Reflection Allgemeine Java-Themen 6
F Google Guice + Generics + Vererbung Allgemeine Java-Themen 5
H Problem mit Java Generics Allgemeine Java-Themen 6
J Generics: Typparameter als Klasse zurückliefern Allgemeine Java-Themen 4
H Generics Allgemeine Java-Themen 5
P Probleme mit Generics Allgemeine Java-Themen 5
B Generics und primitve arrays Allgemeine Java-Themen 6
M Generics Allgemeine Java-Themen 11
1 Collections Generics, internes Verhalten Allgemeine Java-Themen 16
M Probleme mit Generics Allgemeine Java-Themen 5
D Java Generics Allgemeine Java-Themen 8
2 Generics: bounded wildcards Allgemeine Java-Themen 4
J Generics / vermeiden von downcasts Allgemeine Java-Themen 2
2 Generics oder nicht? Allgemeine Java-Themen 8
E Problem mit Generics und Comparable Allgemeine Java-Themen 16
W Erweitern einer Klasse mit Generics Allgemeine Java-Themen 8
H Generics für Methode Allgemeine Java-Themen 14
N Überladen mit Hilfe von Generics Allgemeine Java-Themen 3
S Generics: Fuer Set<T> ein T-Klassenobjekt erhalten? Allgemeine Java-Themen 3
Q Der innere Typ von Generics? Allgemeine Java-Themen 3
N Generics-NullpointerException Allgemeine Java-Themen 7
2 Generics - Typ Allgemeine Java-Themen 12
P Generics Problem Allgemeine Java-Themen 10
S Type safety Warnings beim casten von Generics Allgemeine Java-Themen 6
N Generics Allgemeine Java-Themen 3
V Frage zu Generics Allgemeine Java-Themen 2
S java generics klassen deklaration Allgemeine Java-Themen 7
B hashtable für unterschiedliche Typen - mit Generics Allgemeine Java-Themen 8
E Generics Allgemeine Java-Themen 3
MQue Generics Allgemeine Java-Themen 4
R Problem mit Reflection und Generics Allgemeine Java-Themen 3
C Klassen, die aufeinander verweisen (mit Generics) Allgemeine Java-Themen 16
G Generics - W.card unter Nutzung von Annotationsklasse? Allgemeine Java-Themen 6
G sortieren von generics Allgemeine Java-Themen 10
G Generics in Map. Type of value abhängig vom key Allgemeine Java-Themen 3
A Generics Verständnisfrage Allgemeine Java-Themen 7
Z Generics funzt nicht? Allgemeine Java-Themen 2
T Generics Allgemeine Java-Themen 18

Ähnliche Java Themen

Neue Themen


Oben