103 Stimmen

Warum sollte es mich interessieren, dass Java keine verifizierten Generika hat?

Dies wurde kürzlich in einem Interview als Frage gestellt, die ich dem Kandidaten gestellt habe und die er sich für die Java-Sprache gewünscht hätte. Es ist allgemein bekannt, dass es als störend empfunden wird, dass Java keine reifizierten Generika hat, aber als ich genauer nachfragte, konnte der Kandidat mir eigentlich nicht sagen, welche Art von Dingen er hätte erreichen können, wären sie vorhanden.

Offensichtlich können aufgrund der zulässigen Raw-Typen in Java (und unsicherer Überprüfungen) die Generika umgangen werden und es kann sich so ergeben, dass eine List (zum Beispiel) tatsächlich Strings enthält. Dies könnte offensichtlich unmöglich gemacht werden, wenn Typinformationen reif wären; aber es muss mehr geben als das!

Könnten Personen Beispiele posten von Dingen, die sie wirklich tun würden, wenn reifizierte Generika verfügbar wären? Ich meine, offensichtlich könnten Sie den Typ einer List zur Laufzeit erhalten - aber was würden Sie damit tun?

public  void foo(List l) {
   if (l.getGenericType() == Integer.class) {
       //yeah baby! err, what now?

BEARBEITEN: Ein schnelles Update zu diesem Thema, da die Antworten hauptsächlich darauf abzielen, dass die Notwendigkeit besteht, eine Class als Parameter zu übergeben (zum Beispiel EnumSet.noneOf(TimeUnit.class)). Mir ging es mehr darum, etwas in der Art aufzuzeigen wo dies einfach nicht möglich ist. Zum Beispiel:

List l1 = api.gimmeAList();
List l2 = api.gimmeAnotherList();

if (l1.getGenericType().isAssignableFrom(l2.getGenericType())) {
    l1.addAll(l2); //warum um alles in der Welt würde ich das überhaupt tun?

3voto

Bozho Punkte 570413

Es ist nicht so, dass du etwas Außergewöhnliches erreichen wirst. Es wird einfach einfacher zu verstehen sein. Typenlöschung scheint für Anfänger eine schwierige Zeit zu sein und erfordert letztendlich das Verständnis dafür, wie der Compiler funktioniert.

Meiner Meinung nach sind Generics einfach ein Extra, das eine Menge überflüssiges Casten spart.

1voto

ExCodeCowboy Punkte 870

Etwas, das alle Antworten hier übersehen haben, was für mich ständig ein Kopfschmerz ist, ist, dass Sie aufgrund der gelöschten Typen ein generisches Interface nicht zweimal erben können. Dies kann ein Problem sein, wenn Sie feingranulare Interfaces erstellen möchten.

public interface Service {
           VALUE get(KEY key);
}

public class PersonService implements Service,
        Service //Kann nicht gemacht werden!!

0voto

Adam Punkte 32525

Hier ist einer, der mich heute erwischt hat: Ohne Verkörperung, wenn Sie eine Methode schreiben, die eine varargs-Liste von generischen Elementen akzeptiert ... können die Aufrufer DENKEN, dass sie typsicher sind, aber versehentlich irgendeinen Mist übergeben und Ihre Methode zum Absturz bringen.

Scheint unwahrscheinlich, dass das passiert? ... Sicher, bis ... Sie Class als Ihren Datentyp verwenden. Zu diesem Zeitpunkt wird Ihr Aufrufer Ihnen gerne viele Klassenobjekte senden, aber ein einfacher Tippfehler wird Ihnen Klassenobjekte senden, die nicht zu T passen, und das Unglück nimmt seinen Lauf.

(Anmerkung: Ich könnte hier einen Fehler gemacht haben, aber wenn Sie um "Generics Varargs" googeln, scheint das obige genau das zu sein, was Sie erwarten würden. Das, was dieses zu einem praktischen Problem macht, ist meines Erachtens der Einsatz von Class - die Aufrufer scheinen weniger vorsichtig zu sein :( )


Zum Beispiel verwende ich ein Paradigma, das Klassenobjekte als Schlüssel in Maps verwendet (es ist komplexer als eine einfache Map - aber konzeptionell ist das, was passiert).

zum Beispiel funktioniert dies großartig in den Java Generics (triviales Beispiel):

public  Set getEntitiesPossessingComponent( Class componentType)
    {
        // finde die Entitäten, die irgendwie von dieser Klasse abgebildet sind. Sehr typsicher
    }

zum Beispiel akzeptiert dies ohne Verkörperung in den Java Generics jedes "Class"-Objekt. Und es ist nur eine winzige Erweiterung des vorherigen Codes:

public  Set getEntitiesPossessingComponents( Class... componentType )
    {
        // finde die Entitäten, die irgendwie mit ALLEN diesen Klassen verbunden sind
    }

Die obigen Methoden müssen in einem einzelnen Projekt tausende Male geschrieben werden - daher steigt die Möglichkeit menschlicher Fehler. Fehlerbehebung macht keine "Spaß". Ich versuche derzeit, eine Alternative zu finden, habe aber nicht viel Hoffnung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X