Collections Generics und Reflection

HaVonTe

Mitglied
Hallo,

ich wurde vor kurzem gefragt, ob man mittels Reflection in ein typisiertes Generic (also z.b. List<Integer>) ein Objekt, eines anderes Typs einfügen kann. Also ein String in eine solche Integerliste, z.B.. Ich wusste es nicht und habs auf "nein" getippt. Ich habs dann ausprobiert und die Überraschung war groß. Denn es geht, bei List, aber nicht bei ArrayList.

Beispiel ArrayList:

Java:
package Generics;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class GenericsMain
{
	public static void main(final String[] args)
	{
		final List<Integer> lst = new ArrayList<Integer>();//anonym
		lst.add(new Integer(1));
		//lst.add(new String("")); //<-- compile error
		final Class<? extends List> class1 = lst.getClass();
		//final Class<? extends List<Integer>> class1 = lst.getClass(); //<-- compile error
		try
		{
			final Method[] methods = class1.getMethods();
			for(final Method method : methods)
			{
				System.out.println(method.getName());
				if(method.getName().equals("add"))
				{
					final Class<?>[] parameterTypes = method.getParameterTypes();
					System.out.println(parameterTypes);
					if(parameterTypes.length == 1)
					{
						method.invoke(lst, new Integer(2));
						method.invoke(lst, new Float(2));
						method.invoke(lst, "aa");
					}
					else if(parameterTypes.length == 2)
					{
						method.invoke(lst, 0, new Integer(2));
						method.invoke(lst, 1, new Float(2));
						method.invoke(lst, 2, "bb");
					}
				}
			}
			final Method method = class1.getMethod("add", Object.class);
			//final Method method2 = class1.getMethod("add", Integer.class);//NoSuchMethodException

			method.invoke(lst, new Integer(2));
			method.invoke(lst, new String("sdfsdf"));
			System.out.println(lst);
//Ausgabe: [2, 2.0, bb, 1, 2, 2.0, aa, 2, sdfsdf] //wtf???
		}
		catch(final SecurityException e)
		{
			e.printStackTrace();
		}
		catch(final NoSuchMethodException e)
		{
			e.printStackTrace();
		}
		catch(final IllegalArgumentException e)
		{
			e.printStackTrace();
		}
		catch(final IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch(final InvocationTargetException e)
		{
			e.printStackTrace();
		}
	}

}

Beispiel List:

Java:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class Main
{
	public static void main(final String[] args)
	{
		final MyIntList lst = new MyIntList();

		lst.add(new Integer(1));
		//lst.add(new String("")); //<-- compile error
		final Class<? extends MyIntList> class1 = lst.getClass();
		try
		{
			final Method[] methods = class1.getMethods();
			for(final Method method : methods)
			{
				System.out.println(method.getName());
				if(method.getName().equals("add"))
				{
					final Class<?>[] parameterTypes = method.getParameterTypes();
					System.out.println(parameterTypes);
					if(parameterTypes.length == 1)
					{
						method.invoke(lst, new Integer(2));
						method.invoke(lst, new Float(2));
					}
					else if(parameterTypes.length == 2)
					{
						method.invoke(lst, 0, new Integer(2));
						method.invoke(lst, 1, new Float(2));//IllegalArgumentException
					}
				}
			}
			final Method method = class1.getMethod("add", Object.class);

			method.invoke(lst, new Integer(2));
			method.invoke(lst, new String("sdfsdf"));
			System.out.println(lst);
		}
		catch(final SecurityException e)
		{
			e.printStackTrace();
		}
		catch(final NoSuchMethodException e)
		{
			e.printStackTrace();
		}
		catch(final IllegalArgumentException e)
		{
			e.printStackTrace();
		}
		catch(final IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch(final InvocationTargetException e)
		{
			e.printStackTrace();
		}
	}


	private static class MyIntList implements List<Integer>
	{
		@Override
		public int size()
		{
			return 0;
		}


		@Override
		public boolean isEmpty()
		{
			return false;
		}


		@Override
		public boolean contains(final Object o)
		{
			return false;
		}


		@Override
		public Iterator<Integer> iterator()
		{
			return null;
		}


		@Override
		public Object[] toArray()
		{
			return null;
		}


		@Override
		public <T> T[] toArray(final T[] a)
		{
			return null;
		}


		@Override
		public boolean add(final Integer e)
		{
			return false;
		}


		@Override
		public boolean remove(final Object o)
		{
			return false;
		}


		@Override
		public boolean containsAll(final Collection<?> c)
		{
			return false;
		}


		@Override
		public boolean addAll(final Collection<? extends Integer> c)
		{
			return false;
		}


		@Override
		public boolean addAll(final int index, final Collection<? extends Integer> c)
		{
			return false;
		}


		@Override
		public boolean removeAll(final Collection<?> c)
		{
			return false;
		}


		@Override
		public boolean retainAll(final Collection<?> c)
		{
			return false;
		}


		@Override
		public void clear()
		{
		}


		@Override
		public Integer get(final int index)
		{
			return null;
		}


		@Override
		public Integer set(final int index, final Integer element)
		{
			return null;
		}


		@Override
		public void add(final int index, final Integer element)
		{
		}


		@Override
		public Integer remove(final int index)
		{
			return null;
		}


		@Override
		public int indexOf(final Object o)
		{
			return 0;
		}


		@Override
		public int lastIndexOf(final Object o)
		{
			return 0;
		}


		@Override
		public ListIterator<Integer> listIterator()
		{
			return null;
		}


		@Override
		public ListIterator<Integer> listIterator(final int index)
		{
			return null;
		}


		@Override
		public List<Integer> subList(final int fromIndex, final int toIndex)
		{
			return null;
		}
	}
}

Wenn ich bei dem 2. Beispiel die Ableitung von List auf ArrayList ändere, klappt es dort auch wieder. Also ander konkreten Klassendefinition liegt es nicht.

Mein Frage ist jetzt:

Warum ist das so? Warum kann ich bei List<Integer>... beliebige Objects einfügen, aber bei einer ArrayList<Integer> ... nicht?

MfG
HaVonTe
 
S

SlaterB

Gast
um in eine normale generische Liste etwas anderes einzufügen brauchst du gar nicht unbedingt Reflection
Java:
public class Test {
    public static void main(String[] args)  {
        List<Integer> lst = new ArrayList<Integer>();
        List l = lst;
        l.add("Text");
        System.out.println(l.toString()); // geht soweit
        Integer k = lst.get(0); // hier aber BOOM
    }
}
was du mit 'beim zweiten Beispiel ArrayList statt List' meinst will mir nicht klar werden,

der Unterschied zum ersten Beispiel ist grundsätzlich der, dass du eine feste Klasse definierst, die hat dann Integer intern eingebaut,

während ArrayList<Integer>(); nur dem Compiler bekannt ist, zur Laufzeit liegt eine normale ArrayList für beliebige Objekte vor
 

HaVonTe

Mitglied
List l = lst;
l.add("Text");

Das geht bei mir hier nicht.

was du mit 'beim zweiten Beispiel ArrayList statt List' meinst will mir nicht klar werden,

Na ich hab da doch bei MyIntList nur das Interface List implementiert. Wenn ich statt dessen direkt von ArrayList ableite, also:
Java:
private static class MyIntList extends ArrayList<Integer>
{
}

, dann kann ich auch dort problemlos Strings und alles mögliiche einfügen.
 
Zuletzt bearbeitet:
S

SlaterB

Gast
wenn du die ArrayList drinhast, dann gibt es die Methode add(Object), eben in der Superklasse,
du kannst das Objekt wie in meinem Code auf ArrayList ohne generischen Parameter casten,
das Override kommt nicht zum Tragen

implementierst du dagegen das Interface, so gibt es kein add(Object), nur den Code von dir add(Integer),
und wenn der so fest compiliert ist gibts für Object kein Vorbeikommen,

wiederum in der kürzeren Code-Variante ohne Generics:
Java:
        List<Integer> lst = new MyIntList();
        List l = lst;
        l.add("Text");
ist das BOOM nun schon bei der add()-Zeile

interessant, hatte ich in der Hinsicht auch noch nicht ganz durchschaut,
von korrekter Implementierung des Interfaces kann man so kaum mehr sprechen..,
auch dass das Override nicht viel zählt ist bemerkenswert,
Generics hat schon seine Tücken
 
Zuletzt bearbeitet von einem Moderator:

HaVonTe

Mitglied
An add(Object) in ArrayList hatte ich garnicht gedacht. Die Reflection ist dabei tatsächlich egal. Womit die Frage, "kann man mittels Reflection die Generics überlisten" klar mit "nein" beantwortet werden kann.
Das ArrayList so mies implementiert ist, hätte ich aber nie gedacht. Man lernt nie aus.
 

HaVonTe

Mitglied
An add(Object) in ArrayList hatte ich garnicht gedacht. Die Reflection ist dabei tatsächlich egal. Womit die Frage, "kann man mittels Reflection die Generics überlisten" klar mit "nein" beantwortet werden kann.
Das ArrayList so mies implementiert ist, hätte ich aber nie gedacht. Man lernt nie aus.

Ich muss mich selbst korrigieren. Die Antwort muss lauten: "Ja, es geht."
Der Grund: Per Reflection kann man auf alle Methoden einer Klasse zugreifen. Auch auf die der Elternklassen. Bei (Array)List ist das eben add(Object o). Ohne Reflection ist diese Methode versteckt/überschrieben. Korrigiert mich, wenn ich das schon wieder falsch verstanden habe. Ich lerne noch... :D
 
S

SlaterB

Gast
man kann auch ohne Reflection Generics überlisten, eben mit 'Raw type',
insofern ist deine Aussage genauso sinnvoll mit ja/ nein zu beantworten wie
'mit Regenschirm geht auch morgen die Sonne auf' ;)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Problem mit Reflection und Generics Allgemeine Java-Themen 3
G Reflection objekt mit generics erzeugen Allgemeine Java-Themen 5
M Generics und Reflection Allgemeine Java-Themen 3
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
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
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
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

Ähnliche Java Themen

Neue Themen


Oben