Warum kann eine "Class" -Variable nicht an instanceof übergeben werden?

88

Warum wird dieser Code nicht kompiliert?

    public boolean isOf(Class clazz, Object obj){
        if(obj instanceof clazz){
            return true;
        }else{
            return false;
        }
    }

Warum kann ich keine Klassenvariable übergeben instanceof?

eric2323223
quelle

Antworten:

129

Der instanceofOperator arbeitet mit Referenztypen wie Integerund nicht mit Objekten wie new Integer(213). Sie wollen wahrscheinlich so etwas

clazz.isInstance(obj)

Randnotiz: Ihr Code wird präziser, wenn Sie schreiben

public boolean isOf(Class clazz, Object obj){
    return clazz.isInstance(obj)
}

Ich bin mir jedoch nicht sicher, ob Sie eine Methode mehr benötigen.

Robert Munteanu
quelle
Ich weiß, dass der Code völlig nutzlos ist, ich möchte nur meine Verwirrung demonstrieren :)
eric2323223
6
Integerist kein Klassenliteral. Integer.classwäre ein Klassenliteral (siehe § 15.8.2 des JLS: java.sun.com/docs/books/jls/third_edition/html/… ). Der instanceofBediener verwendet einen "ReferenceType" (auch als Typname bezeichnet) gemäß § 15.20.2 des JLS: java.sun.com/docs/books/jls/third_edition/html/…
Joachim Sauer
3
Ich würde verwenden, clazz.isInstance(obj)da das Objekt bereits geliefert wurde.
Donal Fellows
13

instanceofkann nur mit expliziten Klassennamen verwendet werden (zur Kompilierungszeit angegeben). Um eine Laufzeitprüfung durchzuführen , sollten Sie Folgendes tun:

clazz.isInstance(obj)

Dies hat einen kleinen Vorteil gegenüber clazz.isAssignableFrom(..) da es den Fall obj == nullbesser behandelt.

Eyal Schneider
quelle
5

Wie bereits erwähnt, können Sie eine Klassenvariable nicht übergeben, instanceofda eine Klassenvariable auf eine Instanz eines Objekts verweist , während die rechte Hand von instanceofein Typ sein muss . Das heißt instanceofnicht, dass "y eine Instanz von Objekt x ist", sondern dass "y eine Instanz vom Typ X ist". Wenn Sie den Unterschied zwischen einem Objekt und einem Typ nicht kennen, beachten Sie Folgendes:

Object o = new Object();

Hier ist Objectund oist der Typ ein Verweis auf die Instanz des Objekts mit diesem Typ. So:

if(o instanceof Object)

ist aber gültig

if(o instanceof o)

ist nicht weil o auf der rechten Seite ein Objekt ist, kein Typ.

Genauer gesagt ist eine Klasseninstanz kein Typ, sondern ein Objekt (das von der JVM für Sie erstellt wird). Ist in Ihrer Methode Classein Typ, aber clazzein Objekt (also ein Verweis auf ein Objekt)

Sie benötigen eine Möglichkeit, ein Objekt mit einem Klassenobjekt zu vergleichen. Es stellt sich heraus, dass dies beliebt ist, sodass es Ihnen als Methode des Klassenobjekts zur Verfügung gestellt wird : isInstance().

Hier ist das Java-Dokument für isInstance, das dies besser erklärt:

public boolean isInstance(Object obj)

Legt fest, ob das angegebene Objekt mit dem von dieser Klasse dargestellten Objekt zuweisungskompatibel ist. Diese Methode ist das dynamische Äquivalent der Java-Sprachinstanz des Operators. Die Methode gibt true zurück, wenn das angegebene Object-Argument nicht null ist und in den Referenztyp umgewandelt werden kann, der durch dieses Class-Objekt dargestellt wird, ohne eine ClassCastException auszulösen. Andernfalls wird false zurückgegeben.

Wenn dieses Klassenobjekt eine deklarierte Klasse darstellt, gibt diese Methode true zurück, wenn das angegebene Objektargument eine Instanz der dargestellten Klasse (oder einer ihrer Unterklassen) ist. Andernfalls wird false zurückgegeben. Wenn dieses Klassenobjekt eine Array-Klasse darstellt, gibt diese Methode true zurück, wenn das angegebene Object-Argument durch eine Identitätskonvertierung oder eine erweiterte Referenzkonvertierung in ein Objekt der Array-Klasse konvertiert werden kann. Andernfalls wird false zurückgegeben. Wenn dieses Class-Objekt eine Schnittstelle darstellt, gibt diese Methode true zurück, wenn die Klasse oder eine Oberklasse des angegebenen Object-Arguments diese Schnittstelle implementiert. Andernfalls wird false zurückgegeben. Wenn dieses Klassenobjekt einen primitiven Typ darstellt, gibt diese Methode false zurück.

Parameter: obj - das zu überprüfende Objekt Rückgabe
: true, wenn obj eine Instanz dieser Klasse ist
Seit: JDK1.1

Rick Hanlon II
quelle
3

Erstens instanceofmuss der Operand auf der rechten Seite eine tatsächliche Klasse (z. B. obj instanceof Objectoder obj instanceof Integer) und keine Variable vom Typ sein Class. Zweitens haben Sie einen ziemlich häufigen Anfängerfehler gemacht, den Sie wirklich nicht tun sollten ... das folgende Muster:

if ( bedingter_Ausdruck ) {
    return true;
} else {
    falsch zurückgeben;
}}

Das Obige kann überarbeitet werden in:

return conditional_expression ;

Sie sollten dieses Refactoring immer durchführen, da es eine redundante if ... else-Anweisung eliminiert. In ähnlicher Weise kann der Ausdruck auf dasselbe Ergebnis umgestaltet werden.return conditional_expression ? true : false;

Michael Aaron Safyan
quelle
2
Das ist kein Fehler. Vielleicht ungeschickt, aber total okay. Vielleicht möchten Sie zusätzlichen Code, bevor Sie in absehbarer Zeit zurückkehren ...
Der unglaubliche