Generics Experten Problem

chickenwings

Erfahrenes Mitglied
Hallo,

das Thema Generics scheint doch komplizierter zu sein, als ich dachte.
Habe folgendes Problem:

ein Klasse:
Code:
public class Attribute<T extends Object>
{
	private String name;
	private Class<T> theClazz;

        public Attribute(String name, Class<T> clazz)
	{
		this.name = name;
		this.theClazz = clazz;
	}

        ....
}

Der Aufruf des Konstruktors funktioniert wunderbar, solange ich z.B. folgenden Aufruf mit nicht parameterisierten Generics (hier String) durchführe:
Code:
public static final Attribute<String> myAttr = new Attribute<String>("enable", String.class);

Ist das generische Object allerdings selbst parameterisiert:
Code:
public static final Attribute<List<?>> listAttr = new Attribute<List<?>>("container", List.class);

.. gibt es die Fehlermeldung, dass der entsprechende Konstruktor nicht defniert ist. Das ist auch klar, denn der Konstruktor erwartet nur eine Klasse eines beliebigen Typs.

Wie kann man das erweitern, dass auch komplexere Konstrukte funktionieren?

Grüsse,
chickenwings
 
Hi,
ich habe mich auch vor kurzem erst mit Generics beschäftigt.
Wieso machst du das denn auch doppelt in deinem Code. Es würde (aus meiner Sicht) auch reichen, wenn du nur ein GenericType entweder im Konstruktor übergibst oder eben in den <T>. Da du auf das T ja eh schon zugreifen kannst aus der Attribute-Klasse.
Java:
public class Attribute<T extends Object>
{
	private String name;

	public Attribute(String name)
	{
		this.name = name;
	}
}
Ich kann mich allerdings auch täuschen. :)

Gruß

Fabio
 
Hallo,

nein das geht so leider nicht. In den Parametern gebe ich ja lediglich den Typen vor, der als Parameter im Konstruktor erlaubt ist. Das ganze dient der Typsicherheit.
Über einen Getter will ich ja mal an den Typen der Klasse (Variable clazz) herankommen und dafür dient mir generische Typ.

Grüsse,
chickenwings
 
Achso ok.

Wenn du es so machst:
Java:
public class Attribute<T extends Object>
{
	private String name;
	private final Class<?> clazz;

	public Attribute(String name, Class<?> clazz)
	{
		this.name = name;
		this.clazz = clazz;
	}
	
	public Class<T> getGenericType() {
		return (Class<T>) clazz;
	}
}
Kannst du den Aufruf so machen, wie du es willst:
Java:
Attribute<List<?>> listAttr = new Attribute<List<?>>("container", List.class);

Ich vermute mal, dass das daran liegt, dass du bei List.class keinen GenericType mit übergeben kannst. Deshalb kannst du da nur Attribute<List> schreiben. So würde es dann auch funktionieren.
Dadurch das Class<?> im Konstruktor jetzt aber offen lässt, welche Typen übergeben werden können, kann jetzt List.class und List<?> geschrieben werden.

Ich hoffe, dass das einigermaßen verständlich beschrieben ist von mir.

Gruß

Fabio
 
Hallo,

:-), ja darauf bin ich auch schon gekommen. Problem hierbei ist nur, dass ich dann die Typsicherheit zwischen dem Generic und dem .class-Object des Parameters verliere. Und das soll ja gerade die Stärke des Konstrukts werden. ;-)

Grüsse,
chickenwings
 
Ja klar, dass ist natürlich das Risiko dabei. Aber du kannst es ja wie in deinem Konstrukt mit dem Aufruf machen:
Java:
Attribute<List> listAttr = new Attribute<List>("container", List.class);
Weil: List == List<?>...

// EDIT
Vielleicht ist es das was du suchst...
Java:
public class Attribute<T extends Object>
{
	private String name;
	private T value;
	private final Class<? extends T> clazz;

	public Attribute(String name, Class<? extends T> clazz) {
		this.name = name;
		this.clazz = clazz;
	}

	public Class<T> getGenericType() {
		return (Class<T>) clazz;
	}
}
Wenn du das so machst, hast du deine Typsicherheit. Allerdings must du beim erzeugen des Objekts ein wenig casten. Zumindest bei der List.
Java:
Attribute<String> myAttr = new Attribute<String>("enable", String.class);
Attribute<List<?>> listAttr = new Attribute<List<?>>("container", (Class<? extends List<?>>) List.class);
Class<List<?>> genericType = listAttr.getGenericType();
 
Zuletzt bearbeitet:
Zurück