instanceof bei generischer Methode

mrbela

Bekanntes Mitglied
Hallo!

Ich möchte folgendes mit einer Methode lösen:

Es gibt eine Liste: List<Object> datas (erreichbar unter super.getDatas). Aus dieser möchte ich eine ArrayList eines gewissen Typs herausfilten und diese zurückgeben.

Mein Ansatz

Java:
public <T> T[] blub(T type) {
				
		List<T> list = new ArrayList<>();

		for (int i = start; i < super.getDatas().size(); i++) {
			
			if (super.getDatas().get(i) instanceof T) {
				list.add(super.getDatas().get(i);
			}
		}
	}

Die Fehlermeldung ist aber folgende:

Code:
Cannot perform instanceof check against type parameter T. Use instead its erasure Object since generic type information will be erased at runtime

Jemand ne Idee wie man das lösen könnte? :/
 
Unter der Voraussetzung, dass der Parameter type nicht null ist, kannst Du mit dessen Class-Objekt einiges anstellen. Z.B.
Java:
public <T> T[] blub(T type) {
                
        // Hier das Class-Objekt ermitteln. Wenn type
        // null wäre, würd hier ne NullPointer fliegen.
        final Class<T> typeClass = type.getClass();

        List<T> list = new ArrayList<>();
 
        for(Object current: super.getDatas()) {

           // Diese Variante prüft auf Klassengleichheit. Das ist
           // meist das, was man mit instanceof will, weil man 
           // vergisst, dass instanceof auch für Subklassen true ist
           if(current != null && current.getClass() == typeClass) {
              list.add((T)current);
           }

           // Wenn Du aber auch Subklassen akzeptieren möchtest
           // geht's so:
           if(current != null && typeClass.isAssignableFrom(current.getClass()) {
              list.add((T)current);
           }
        }
    }
Guter Stil wäre es, die Prüfmethode als Interface-Methode zu deklarieren und davon Implementierungen zu programmieren. Ich denke da an etwas analog dem FileFilter (Java Platform SE 7 ) Nur, dass Dein Filter halt Listenelemente ablehnt/annimmt, statt File-Objekte.
 
Zuletzt bearbeitet von einem Moderator:
Ich hab auch ein wenig rumprobiert:

Java:
import java.util.ArrayList;
import java.util.List;

public class ListFilter {

	static <T> List<T> filterList(List<?> list, Class<T> c) {
		final List<T> result = new ArrayList<>();
		for (Object obj : list) {
			if (obj.getClass().equals(c)) {
				@SuppressWarnings("unchecked")
				final T t = (T) obj;
				result.add(t);
			}
		}
		return result;
	}

	static void printList(List<?> list) {
		for (Object o : list) {
			System.out.print(o + ", ");
		}
		System.out.println();
	}

	public static void main(String[] args) {
		List<Object> original = new ArrayList<>();
		original.add(Integer.valueOf(1));
		original.add("Hallo");
		original.add("Welt");
		original.add(Integer.valueOf(2));
		original.add(Integer.valueOf(3));
		original.add("Noch ein String");

		System.out.println("Original:");
		printList(original);

		List<Integer> gefiltert = filterList(original, Integer.class);
		System.out.println("\nGefiltert:");
		printList(gefiltert);
	}
}

Ausgabe:
Code:
Original:
1, Hallo, Welt, 2, 3, Noch ein String, 

Gefiltert:
1, 2, 3,
 
Danke, Leute!

Ich hab mcih selbst mal auf den Pfad der Suchenden begeben und habe folgende Lösung gefunden, die auch funktioniert:

Java:
datas.get(i).getClass().isAssignableFrom(tClass)

Ich habe das ganze noch mit einer StartPosition versehen: Ab dieser Position wird in der Liste gesucht, sobald ein Typ anders ist, wird abgebrochen..

Er findet also "nur" Felder innerhalb einer Liste:

Liste sei {0, 1, 1, 1 , 0, 1, 1} und ich filter mit StartPostion = 1 und Typ 1, dann kommen nur die ersten drei 1er raus, weil dann erstmal die 0 kommt un er abbricht.

Klingt komisch, aber ich hab die Methode so gebraucht. 😉

Hier noch der Volständigkeit halber der Code:

Java:
	public <T> List<T> filter(int startPosition, Class<T> tClass) {
		
		List<T> list = new ArrayList<>();

		for (int i = startPosition; i < datas.size(); i++) {
			
			if (datas.get(i).getClass().isAssignableFrom(tClass)) {
				list.add((T) datas.get(i));
			} else {
				break;
			}
		}
		
		return list;
	}
 

Zurück
Oben