'İnstanceof' operatörü arayüzler ve sınıflar için farklı davranır


88

instanceofJava'da operatörün aşağıdaki davranışları hakkında bilgi almak istiyorum .

interface C {}

class B {}

public class A {
    public static void main(String args[]) {
        B obj = new B();
        System.out.println(obj instanceof A);      //Gives compiler error
        System.out.println(obj instanceof C);      //Gives false as output
    }
}

Neden böyle? Orada arasında bir ilişki olduğunu interface Cve class Bancak bir o durumda iken sahte verir obj instanceof Ao derleyici hata veriyor?


12
Not: olarak değiştirirseniz Object obj = new B(), derlenir.
user253751

1
Derleyici Hatası size ne anlatıyor?
karfau

Eğer class Bis ise finalo obj instanceof Czaman da derlenmeyecektir, çünkü eğer Bhiç alt tipe sahip olamazsa , o zaman bununla ilgisiz olduğu garanti edilir C.
jaco0646

Yanıtlar:


127

Java'nın birden fazla sınıf mirası olmadığı için, derleme sırasında objnesnenin Balt türü olamayacağı kesin olarak bilinir A. Öte yandan, muhtemelen arayüzün alt tipi olabilir C, örneğin bu durumda:

interface C {}

class B {}

class D extends B implements C {}

public class A {
    public static void main(String args[]) {
        B obj = new D();
        System.out.println(obj instanceof C);      //compiles and gives true as output  
    }
}

Yani sadece obj instanceof Cifade derleyicisine bakmak bunun doğru mu yanlış mı olacağını önceden söyleyemez, ancak obj instanceof Aona bakmak bunun her zaman yanlış olduğunu, dolayısıyla anlamsız olduğunu ve bir hatayı önlemenize yardımcı olduğunu bilir. Programınızda yine de bu anlamsız kontrolün olmasını istiyorsanız, şunlara açık bir çevrim ekleyebilirsiniz Object:

System.out.println(((Object)obj) instanceof A);      //compiles fine

1
Anlamsız bir çekin diğer bir çeşidi de kullanmaktırA.class.isAssignableFrom(obj.getClass())
David Ehrmann

Java has no multiple class inheritanceEvet dediğiniz açıklamanızla biraz kafam karıştı, evet katılıyorum ama bu durumda nasıl uygulanıyor çünkü ne B ne de A herhangi bir genişletme yapmıyor, öyleyse neden burada çoklu kalıtım var. Açıklayabilirseniz yardımcı olur mu?
codegasmer

@codegasmer Geç yanıt: Java bir sınıfın birden fazla başka sınıftan miras almasına izin verdiyse, "D sınıfı A, B" veya benzeri bir şey yapılıp "B obj = new D ()" yapılabilir ve "obj Orjinal sorudaki "A" örneği derlenir (halihazırda derlemez) - aslında daha iyi derlenmişti, çünkü doğru olarak değerlendirilmesi bekleniyordu. Ancak, herhangi bir şeyin hem B hem de A olmasına izin verilmiyorsa, objenin B tipi olarak tanımlandığı "obj instanceof A" ifadesi mantıklı bir şekilde saçma olarak değerlendirilebilir.
mjwach

"Bu anlamsız denetimi yine de yapmak istiyorsanız" - anlamsız olması gerekmez, sanki bu sınıflar başka bir kitaplıktan / çerçeveden geliyormuş gibi, o zaman çalışma zamanında farklı bir sürümü kullanma şansınız vardır B extends A. Hayatımda aslında (A)(Object)bçalışma zamanında olduğu gibi bu kadar tuhaf kontroller ve yayınlar yapmam gerekiyordu, aslında gerçek olması mümkündü.
GotoFinal

1

finalAşağıdaki sınıf bildirimindeki değiştiriciyi kullanarak Test, arayüzü uygulayabilecek bir alt sınıfın olamayacağı garanti edilir Foobar. Bu durumda, açıktır Testve Foobarbirbirleri ile uyumlu değildir:

public final class Test {

    public static void main(String[] args) {
        Test test = new Test();
        System.out.println(test instanceof Foobar); // Compiler error: incompatible types
    }
}

interface Foobar {
}

Aksi takdirde, Testbildirilmezse final, Testarabirimi bir alt sınıfın uygulaması mümkün olabilir . Derleyici bu nedenle test instanceof Foobarbu durumda ifadeye izin verir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.