2 Stimmen

Verwendung allgemeiner Parameter mit der statischen compareObject-Methode

Ich möchte alle "ungeprüften" Warnungen aus dieser allgemeinen Dienstprogrammmethode (Teil einer größeren Klasse mit einer Reihe ähnlicher Methoden) entfernen. Notfalls kann ich @SuppressWarnings("unchecked") verwenden, aber ich frage mich, ob ich Generika richtig verwenden kann, um die Warnung zu vermeiden.

Die Methode soll es dem Aufrufer ermöglichen, zwei Objekte durch Übergabe an compareTo zu vergleichen, mit der Ausnahme, dass, wenn das Objekt eine Zeichenkette ist, die Groß- und Kleinschreibung nicht berücksichtigt wird.

public static int compareObject(Comparable o1, Comparable o2)
{
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

Dies war mein erster (fehlerhafter) Lösungsversuch. Die Parameter funktionieren gut, aber die Zeile o1.compareTo(o2) hat einen Kompilierfehler "Die Methode compareTo(capture#15-of ?) im Typ Comparable ist für die Argumente (Comparable) nicht anwendbar".

public static int compareObject(Comparable<?> o1, Comparable<?> o2)
{
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

Irgendwelche Vorschläge?

0 Stimmen

Nur als eine allgemeine Anmerkung, sollten Sie wahrscheinlich mit compareToIgnoreCase statt konvertieren beide Zeichenketten in Großbuchstaben sein. Ihre Methode könnte subtile Bugs mit der Internationalisierung haben (siehe die toUpperCase-Dokumentation).

2voto

Michael Myers Punkte 183216

Ich habe das gerade ausprobiert:

public static <T extends Comparable> int compareObject(T o1, T o2) {
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

Es kompiliert, aber gibt eine ungeprüfte Cast-Warnung auf den compareTo()-Aufruf.
Ich habe versucht, es zu ändern

public static <T extends Comparable<T>> int compareObject(T o1, T o2) {

und die String-Prüfungen lassen sich nicht kompilieren ("inconvertible types: found: T, required: String"). Ich denke, das muss aber nahe dran sein.


EDIT: Wie in den Kommentaren hervorgehoben, ist dies ein Fehler in javac . Die zweite Form ist zwar korrekt, lässt sich aber derzeit nicht kompilieren. So verrückt es auch aussehen mag, dies ist der Code, der ohne Warnungen funktioniert:

public static <T extends Comparable<T>> int compareObject(T o1, T o2) {
    if (((Object) o1 instanceof String) && ((Object) o2 instanceof String))
        return ((String) (Object)o1).toUpperCase().compareTo(((String) (Object)o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

Wie Sie sehen können, besteht der einzige Unterschied darin, dass alle redundanten Casts an Object .

0 Stimmen

Bei der letztgenannten Signatur tritt dieser Fehler nicht auf. Welche Version von javac verwenden Sie?

0 Stimmen

Java 6. Ich bekomme rote Kringel in NetBeans, und ich habe gerade den gleichen Fehler, wenn ich es von der Kommandozeile versucht.

0 Stimmen

Eclipse macht das nichts aus, aber das JDK schon, sowohl Version 5 als auch 6. Ich würde sagen, es ist ein Fehler in der JDK.

1voto

Frederic Morin Punkte 8473

Hier ist, wonach Sie suchen:

public static <T extends Comparable<T>> int compareObject(T o1, T o2) {
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

0 Stimmen

Wenn die entsprechenden Fehler in javac behoben sind, ist dies die zu verwendende Signatur.

0 Stimmen

Bestätigt-- funktioniert und kompiliert in Eclipse, kompiliert nicht in JDK. Bizarr.

1voto

Hans-Peter Störr Punkte 24030

Ich hoffe, Sie sind sich bewusst, dass viele der hier vorgestellten Ansätze die Semantik der Methode verändern. Mit der ursprünglichen Methode könnten Sie Objekte unterschiedlichen Typs vergleichen, wenn sie dies erlauben, aber mit

public static <T extends Comparable<T>> int compareObject(T o1, T o2)

können Sie diesen Vergleich nicht mehr durchführen. Eine Variante, die dies ermöglicht, wäre

    public static int compareObject2(Comparable<Object> o1, Comparable<Object> o2) {
    if (((Object) o1 instanceof String) && ((Object) o2 instanceof String))
        return ((String) (Object)o1).toUpperCase().compareTo(((String) (Object)o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

(Ich habe den Workaround für den erwähnten Javac-Bug eingefügt.) Aber das erhöht nicht die Typsicherheit oder so, also ist es in diesem Fall wahrscheinlich besser, die verständlichere nicht-generische Methode zu verwenden und mit einem @SuppressWarnings("unchecked") . Es gibt so etwas wie eine übermäßige Verwendung von Generika.

0 Stimmen

Danke, das ist gut zu wissen. Ich bin eigentlich mit der neuen Semantik der beantworteten Lösung einverstanden, aber es ist hilfreich, dies zu sehen.

0voto

Bartosz Klimek Punkte 555

Wie sieht es mit dem Folgenden aus?

  public static <T extends Comparable<T>> int compareObjects(T o1, T o2)
  {
    return o1.compareTo(o2);
  }

  public static int compareObjects(String o1, String o2)
  {
    return o1.compareToIgnoreCase(o2);
  }

Der Nachteil ist, dass beim Aufruf von compareObjects() mit Objekten, die zufällig Strings sind, wird der Compiler Ihren Aufruf an die erste Funktion binden, und Sie werden mit dem Groß-/Kleinschreibung-unterscheidenden Vergleich enden.

-1voto

jfpoilpret Punkte 10291

Haben Sie die folgenden Tests durchgeführt?

public static <T> int compareObject(Comparable<T> o1, Comparable<T> o2)
{
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

Ich denke, es sollte korrekt funktionieren.

0 Stimmen

Ich habe es gerade überprüft, und es ist nicht der Fall.

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