510 Stimmen

Was ist der Unterschied zwischen instanceof und Class.isAssignableFrom(...)?

Welche der folgenden Möglichkeiten ist besser?

a instanceof B

oder

B.class.isAssignableFrom(a.getClass())

Der einzige Unterschied, der mir bekannt ist, besteht darin, dass die erste Methode false zurückgibt, wenn 'a' null ist, während die zweite eine Ausnahme auslöst. Liefern sie sonst immer das gleiche Ergebnis?

17 Stimmen

F t )

2 Stimmen

Téô T '

1voto

Sagan Punkte 1513

Wie wäre es mit ein paar Beispielen, um es in Aktion zu zeigen...

@Test
public void isInstanceOf() {
    Exception anEx1 = new Exception("ex");
    Exception anEx2 = new RuntimeException("ex");
    RuntimeException anEx3 = new RuntimeException("ex");

    //Base case, handles inheritance
    Assert.assertTrue(anEx1 instanceof Exception);
    Assert.assertTrue(anEx2 instanceof Exception);
    Assert.assertTrue(anEx3 instanceof Exception);

    //Other cases
    Assert.assertFalse(anEx1 instanceof RuntimeException);
    Assert.assertTrue(anEx2 instanceof RuntimeException);
    Assert.assertTrue(anEx3 instanceof RuntimeException);
}

@Test
public void isAssignableFrom() {
    Exception anEx1 = new Exception("ex");
    Exception anEx2 = new RuntimeException("ex");
    RuntimeException anEx3 = new RuntimeException("ex");

    //Correct usage = The base class goes first
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx1.getClass()));
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx2.getClass()));
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx3.getClass()));

    //Incorrect usage = Method parameter is used in the wrong order
    Assert.assertTrue(anEx1.getClass().isAssignableFrom(Exception.class));
    Assert.assertFalse(anEx2.getClass().isAssignableFrom(Exception.class));
    Assert.assertFalse(anEx3.getClass().isAssignableFrom(Exception.class));
}

0voto

isAssignableFrom(A, B) =

if (A == B) return true
else if (B == java.lang.Object) return false
else return isAssignableFrom(A, getSuperClass(B))

Der obige Pseudocode ist eine Definition der Frage, ob Referenzen des Typs/der Klasse A von Referenzen des Typs/der Klasse B zugewiesen werden können. Es ist eine rekursive Definition. Für einige mag sie hilfreich sein, für andere verwirrend. Ich füge sie für den Fall hinzu, dass jemand sie nützlich finden sollte. Dies ist nur ein Versuch, mein Verständnis zu erfassen, es ist nicht die offizielle Definition. Sie wird in einer bestimmten Java-VM-Implementierung verwendet und funktioniert für viele Beispielprogramme, so dass ich zwar nicht garantieren kann, dass sie alle Aspekte von isAssignableFrom erfasst, aber sie ist nicht völlig daneben.

0voto

Yura Punkte 1626

In Bezug auf die Leistung "2" (mit JMH) sprechen:

class A{}
class B extends A{}

public class InstanceOfTest {

public static final Object a = new A();
public static final Object b = new B();

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testInstanceOf()
{
    return b instanceof A;
}

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testIsInstance()
{
    return A.class.isInstance(b);
}

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testIsAssignableFrom()
{
    return A.class.isAssignableFrom(b.getClass());
}

public static void main(String[] args) throws RunnerException {
    Options opt = new OptionsBuilder()
            .include(InstanceOfTest.class.getSimpleName())
            .warmupIterations(5)
            .measurementIterations(5)
            .forks(1)
            .build();

    new Runner(opt).run();
}
}

Es gibt:

Benchmark                            Mode  Cnt  Score   Error  Units
InstanceOfTest.testInstanceOf        avgt    5  1,972 ? 0,002  ns/op
InstanceOfTest.testIsAssignableFrom  avgt    5  1,991 ? 0,004  ns/op
InstanceOfTest.testIsInstance        avgt    5  1,972 ? 0,003  ns/op

Daraus können wir schließen: instanceof so schnell wie isInstance() y isAssignableFrom() nicht weit entfernt (+0,9% Ausführungszeit). Also kein wirklicher Unterschied, was auch immer Sie wählen

-2voto

Milan Punkte 5

Einige Tests, die wir in unserem Team durchgeführt haben, zeigen, dass A.class.isAssignableFrom(B.getClass()) arbeitet schneller als B instanceof A . Dies kann sehr nützlich sein, wenn Sie dies bei einer großen Anzahl von Elementen überprüfen müssen.

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