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:
Beispiel List:
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
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