Generics sind zu streng - oder ich zu naiv?

G

Gonzo17

Gast
Servus,

irgendwie bin ich auf ein Konstrukt gestoßen, das ich nicht ganz verstehe. Es geht um Generics, die habe ich vorher selten aktiv verwendet und hab jetzt einen Fall, in dem es durchaus Sinn macht. Allerdings stoße ich dabei an ne Grenze, die ich nicht ganz verstehe. Im Folgenden erläutere ich mal anhand eines Beispiels, wo mein Problem liegt.

Zu Beginn habe ich eine abstrakte Klasse definiert, die ich für alle späteren Implementierungen benutzen möchte. Das sieht so aus:

Java:
public abstract class Abstract<T extends Type> {
	public void doSomethingWith(T object) {
		System.out.println(object);
	}
}

Dabei ist
Code:
Type
selbst ein Interface, da es eben auch verschiedene Typen geben kann. In diesem Fall ist es nicht wichtig, was dieses Interface wirklich bereitstellt, deswegen sieht es für das Beispiel so aus:

Java:
public interface Type {
}

Für die verschiedenen Typen erstelle ich Enums, die dann eben Parameter verwalten. Das sieht so aus:

Java:
public enum Type1 implements Type {
	A, B, C;
}

Und die Implementierung selbst schaut folgendermaßen aus:

Java:
public class Implementation1 extends Abstract<Type1> {
}

Dass hier auch nichts weiter geschieht, ist erstmal egal, es geht nur darum, dass die vererbte Methode eben nicht
Code:
Type
, sondern wirklich
Code:
Type1
erwartet! Ginge es beispielsweise um Getter und Setter, dann könnte ich sicherstellen, dass hier nur gewollte, konkrete Subtypen des allgemeinen Interfaces verwendet werden.

Jetzt wird es interessant. An einer anderen Stelle möchte ich nun ein Objekt erzeugen, das auf jeden Fall vom Typ
Code:
Abstract
ist. Ob es jetzt
Code:
Implementation1
oder
Code:
Implementation2
ist, kann ich nicht sagen, ist mir aber auch relativ egal. Sieht dann in etwa so aus:

Java:
public class Test {
	public static void main(String[] args) {
		Abstract<?> var = giveMeImplementationForAbstract();
		Type test = Type1.A;
		var.doSomethingWith(test);
	}
	
	public static Abstract<?> giveMeImplementationForAbstract(){
		return new Implementation1();
	}
}

Aber Zeile 5 verbietet er mir:
The method doSomethingWith(capture#2-of ?) in the type Abstract<capture#2-of ?> is not applicable for the arguments (Type1)

Macht auch keinen Unterschied, wenn ich statt
Code:
<?>
sowas wie
Code:
<? extends Type>
schreibe. Und wo genau ist das Problem?

Nun, so richtig verstehe ich die Ursache des Fehlers nicht. Deswegen frage ich euch. Irgendwo muss ich einen Denkfehler haben. Denn eigentlich würde ich erwarten, dass diese Methode ein Argument vom Typ
Code:
Type
annehmen würde. Tut sie aber nicht. Was genau soll denn da stehen? Kennt jemand einen eleganten Weg das anders zu lösen?
 
Zuletzt bearbeitet von einem Moderator:
S

SlaterB

Gast
du definierst doch, dass die Methode doSomethingWith() nur genau mit dem generischen Parameter T aufgerufen werden darf,
dieser ist unbekannt,

warum sollten beliebige Type-Objekte akzeptiert werden? wenn ja, dann ändere den Parametertyp der Methode von T auf Type (*)

edit:
> es geht nur darum, dass die vererbte Methode eben nicht Type , sondern wirklich Type1 erwartet!

hmm, das scheint dir bewußt und nicht das Ziel zu sein

> Denn eigentlich würde ich erwarten, dass diese Methode ein Argument vom Typ Type annehmen würde.

????

die (überschriebene) Methode ändert jedenfalls nicht ihre Erwartungen, je nachdem welchen Typ die Variable des Objektes gerade hat,
es wird entweder genau der Vertrag der Klasse eingehalten, der mit dem Interface übereinstimmen kann,
oder sich bei <?> rausgeredet dass man eben 'nichts genaues weiß man nicht', also nichts übergeben kann

edit2:
ok, überschrieben wird ja nicht, aber das kann Java an dieser Stelle nicht wissen, bzw. ergibt kaum Sinn, siehe (*) oben,
du kannst durch Casten Type durchaus übergeben:


also einfach nur
Java:
Abstract var = giveMeImplementationForAbstract();

oder

Abstract<Type> var = (Abstract)giveMeImplementationForAbstract();
generisch falsch ist es letztlich immer, ich sehe nun aber deinen Punkt, nach vielen edits ;)
 
Zuletzt bearbeitet von einem Moderator:
G

Gonzo17

Gast
generisch falsch ist es letztlich immer, ich sehe nun aber deinen Punkt, nach vielen edits ;)

Hab brav abgewartet, wann es wohl ein Ende nimmt mit den Edits :D

Gut, bzw nicht gut. Ich will ja Generics richtig verwenden und nicht "irgendwie". Wenn ich so wie du vorgeschlagen hast die Type Argumente weglasse, dann gibts ein unschönes Warning:

Abstract is a raw type. References to generic type Abstract<T> should be parameterized

Edit: Übrigens gleiches Problem beim zweiten Vorschlag, ein "unchecked cast" wäre das in dem Fall.
 
Zuletzt bearbeitet von einem Moderator:
S

SlaterB

Gast
wie gesagt ist das ein Workaround unter Umgehung aller Sicherheitsmaßnahmen, wenn du selber weißt dass es gut geht,
damit kann man in Teufels Küche kommen, etwa wenn Implementation1 die Methode tatsächlich überschreibt, dann mit Type1 als Parameter,
und ein Objekt von [c]Type2 implements Type[/c] übergeben wird
-> ClassCastException
zu empfehlen ist es also ganz und gar nicht,

du musst dich genau an die vorliegenden Informationen halten, dann meckert Java nicht, dann geht alles:
a) entweder bekommt doSomethingWith() Type statt T als Parameter, Generics fällt aus
b) oder aber es muss zwingend ein Objekt vom genau richtigen generischen Typ T übergeben werden, da gibt es keine Ausnahmen, warum auch?

ich sehe inzwischen zwei kleine Varianten, die du im Sinn haben könntest?:
- möchtest du beliebige Type-Objekte übergeben? wie gesagt a) zu empfehlen, ganz einfach, wenn T bleibt, sehe ich schwarz

- oder meinst du dass du ja mit Type1 durchaus das richtige Objekt hast, also diese Übergabe klappen müsse auch wenn an dieser Stelle für Java nicht alle Informationen vorliegen?
nun, dann gilt, dass da nichts zu retten ist,
ist einmal die Generics-Kette unterbrochen, kann sie quasi nicht respektabel repariert werden,

immer bleibt die Unsicherheit, dass falsche Objekte ganz genauso wie richtige Objekte behandelt werden,
es gibt auch nur schlecht Möglichkeiten, den tatsächlichen generischen Parameter auszulesen,
wobei bei festen Klassen wie Implementation1 eher möglich

ein nicht (ausreichend) generisches Objekt wieder auf Abstract<Irgendwas> zu casten ergibt IMMER eine Warning,
je nachdem wie sicher man sich selber ist, kann man sie ignorieren oder eben nicht
 
Zuletzt bearbeitet von einem Moderator:
Ähnliche Java Themen
  Titel Forum Antworten Datum
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 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
T Warnungsfreie Verwendung von Generics Allgemeine Java-Themen 11
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
G ComboBox: Nur eine Art Klasse zulassen (Generics) Allgemeine Java-Themen 3
J Generics Expertenwissen? Allgemeine Java-Themen 5
S Generics-Problem Allgemeine Java-Themen 3
T Generics und Wil-dcards Allgemeine Java-Themen 8
Q Typen von Generics & Casten Allgemeine Java-Themen 3
S Generics Allgemeine Java-Themen 2
R Problem mit Generics Allgemeine Java-Themen 2
G Trotz Generics Cast-Fehler! Allgemeine Java-Themen 5
T TreeMap durch Comparator mit Generics sortieren Allgemeine Java-Themen 9
T Generics und instanceof Allgemeine Java-Themen 10
T Generics und Exceptions Allgemeine Java-Themen 6
M Beliebig viele Typen bei Generics Allgemeine Java-Themen 3
G Reflection objekt mit generics erzeugen Allgemeine Java-Themen 5
S Singleton Pattern mit Generics Allgemeine Java-Themen 4
G Generics und Comparable Allgemeine Java-Themen 11
H Generics Problem Allgemeine Java-Themen 3
F Generics: spricht etwas dagegen raw types zu verwenden? Allgemeine Java-Themen 31
M Generics - besser programmieren, Warnung umgehen Allgemeine Java-Themen 4
E Java, UML, Generics Allgemeine Java-Themen 6
P Array von Vectoren + Generics Allgemeine Java-Themen 6
M ArrayList erweitern - generics Allgemeine Java-Themen 4
E Generics -> UML Allgemeine Java-Themen 4
G Generics: Instanzieren einer Klasse in einer Methode. Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben