Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why both subclass and superclass are true while using instanceof? [duplicate]

Tags:

java

interface

Sorry that I had a mistake while posting. The class that implements I should be B rather than A in this case. And here it is where I find confusing. Also, if it is class C that implements I rather than A or B, the results are still the same.

interface I{}

public class A{
    A() {
        System.out.print("A: " + (this instanceof I) + " ");
    }
    public static void main(String[] args) {
        new C();
    }
}

class B extends A implements I {
    B() {
        System.out.print("B: " + (this instanceof I) + " ");
    }
}

class C extends B {
    C() {
        System.out.print("C: " + (this instanceof I) + " ");
    }
}

Why both subclass and superclass are true while using instanceof?

The result of this code is:

A: true
B: true
C: true 
like image 942
Lei Zuo Avatar asked Oct 20 '25 14:10

Lei Zuo


2 Answers

The instanceof operator checks whether the given object is a sublcass (not necessarily a true subclass) of the given class. This does in general mean that you can cast the object to that class (reduce the view to it).

So for example if we have an ArrayList we could cast it to List, also instanceof would return true if we check that ArrayList against List. So in your example of course you could do

new C() instanceof B // true
new B() instanceof A // true

However the classes also inherit such properties from their parents. Thus the class C is of course also subclass of A, since it is subclass of B and B is subclass of A, so we get

new C() instanceof A // true

And the same holds for interfaces too, we get

new A() instanceof I // true

and by inheritance

new B() instanceof I // true
new C() instanceof I // true

Practical example

Take a look at the following example

public interface CanBark { }

public class Dog implements CanBark { }

public class Pug extends Dog { }

of course the Pug is a Dog and since Dog is a CanBark the Pug is also a CanBark, we get

new Pug() instanceof Dog     // true
new Dog() instanceof CanBark // true
new Pug() instanceof CanBark // true

Details of instanceof

The Java Language Specification (§15.20.2) defines the behavior of the instanceof operator as

At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast (§15.16) to the ReferenceType without raising a ClassCastException. Otherwise the result is false.

Whereas the cast (§15.16) behaves like

[...] or checks, at run time, that a reference value refers to an object whose class is compatible with a specified reference type.

Therefore the casting refers to the casting rules specified in (§5.5). Your specific case is defined in (§5.5.1) as

If T (target) is an interface type:

If S (source) is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.

Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).

like image 56
Zabuzard Avatar answered Oct 22 '25 06:10

Zabuzard


This is a fundamental of object oriented programming. Let me give you an example which might help you to feel why subclasses get the behavior of interfaces implemented by parent class. Let me know if this helps.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

interface Flyable {
    /* Guys, Don't worry about what kind of flyable object you are talking to. 
     * just call me if you want to request someone to fly. */
    public void fly();

}

/*
 * Bird is abstract since there is nothing called 'Bird' existing in the world.
 * It should be either a Crow, Pegion, Sparrow and so on.
 */

abstract class Bird implements Flyable {

    public void fly() {
    /*  All birds follow same sequence of actions to fly.
     This method contains set of instructions to fly. */
    }

    // call this method to know where the bird was born
    public abstract String getCountry();
}


class Sparrow extends Bird {

    private String country;

    // I am responsible to give birth to a new sparrow.
    Sparrow(String beakColor, int weight, String bodyColor, String countryToLive) {
        this.country = countryToLive;

        // code to give birth to a new sparrow.
    }

    // Call me to know where i'm born
    public String getCountry() {
        return this.country;
    }


}

class Helicopter implements Flyable {

    private Date manufacturDate;
    private int engineCapacity;

    Helicopter() {
        /* sequence of instruction on how to assemble a new helicopter with default specifications */
    }

    @Override
    public void fly() {
        /* sequence of instruction on how helicopter should fly
         * Of course it will be different from how birds fly
         *  */

    }

    public Date getManufacturDate() {
        return this.manufacturDate;
    }

    public int getEngineCapacity() {
        return this.engineCapacity;
    }

}


class RandomSkyObjectsHandler {

    public static List<Flyable> getFewFlyableObjectsOfAnyType() {
        List<Flyable> randomList = new ArrayList<Flyable>();
        Sparrow sp1 = new Sparrow("black", 50, "brown", "India");
        Helicopter h1 = new Helicopter();
        Helicopter h2 = new Helicopter();
        Sparrow sp2 =  new Sparrow("Brown", 60, "white", "Kenya");
        Helicopter h3 = new Helicopter();
        Sparrow sp3 = new Sparrow("white", 70, "black", "USA");

        Flyable[] f = {sp1, sp2, h1, sp3, h2, h3};
        randomList = Arrays.asList(f);
        return randomList;


    }
}


public class TestProgramExecutor {
    public static void main(String... commandLineArguments) {

        List<Flyable> mixOfFlyingStuff = RandomSkyObjectsHandler.getFewFlyableObjectsOfAnyType();

        /* here is the beauty of OOPS. I don't need the knowledge of whether i'm telling a helicopter to fly or a sparrow to fly.
         * I'm just pretty sure that I'm talking to a flyable object and it understand if i say fly();
         * */

        for(Flyable f: mixOfFlyingStuff) {

            f.fly();
        }
    }
}
like image 24
Jinnah Avatar answered Oct 22 '25 04:10

Jinnah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!