58

For this example:

public class Foo{}

public class Bar extends Foo{}

....

void myMethod(Foo qux){
   if (checkInstance(qux,Foo.class)){
     ....
   }
}

How can I check if qux is an instance of Foo (but not an instance of its subclass of foo)? That is:

  • checkInstance(qux,Foo.class)=true
  • checkInstance(qux,Bar.class)=false

Is there some kind of statement like instanceof for this check? or I should use qux.getClass().equals(Foo.class)

Christoph S.
  • 585
  • 3
  • 16
Addev
  • 31,819
  • 51
  • 183
  • 302
  • Hope this helps http://www.java-samples.com/showtutorial.php?tutorialid=332 You can use `qux instanceof Foo` – DaGLiMiOuX May 22 '13 at 09:51
  • @Selvin Using instanceof does not necessarily mean the app design is wrong. For example it is used in adapters when you are trying to map data to multiple view types. – Dazzy_G May 22 '13 at 09:55
  • 1
    but checking if object is instance of Foo but not Bar(when Bar extends Foo) is wrong app design – Selvin May 22 '13 at 09:56

7 Answers7

82

If you have to do this, the only way would be the getClass().equals(Foo.class) option you've suggested.

However, the goal of OO design is to allow you to treat any Foo in the same fashion. Whether or not the instance is a subclass should be irrelevant in a normal program.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • 33
    I think a lot of stack exchange questions are about situations that are out of the normal. – Warren Dew Apr 27 '14 at 18:08
  • 1
    @WarrenDew I agree. But a high proportion are people seeking a way to implement their own solution to a problem, when perhaps a better solution exists. When you find yourself breaking OO principles in an OO language, it's a pretty good indication you're off piste. – Duncan Jones Aug 03 '16 at 07:28
  • I don't understand what is a _better alternative_ that is _congruent with OO principles_ – ycomp Nov 30 '16 at 17:22
  • hmm, I guess separating `Foo` into 2 classes `Foo` and `SuperFoo`and have `Bar` descend from `SuperFoo` might be some way to fudge it but the code would become more complicated because of that. So it might be more OO but i'm not so sure it is better. – ycomp Nov 30 '16 at 17:25
  • ok since I have an IDE that can refactor, that is what I'll do ) maybe it will save me from some bugs in the future (althpugh I prefer the prefix `Abstract` to `Super`, it's just I can't edit old comments) – ycomp Nov 30 '16 at 17:46
  • In a unit test you would probably want to test for exact class, and not use `instanceof` – anttikoo Feb 19 '17 at 10:28
  • How about the case when you're overriding the `equals` function? I need to be sure that the object I am comparing my object to, is of the same class, and not of a subclass. I do not want a `Manager` object to be equal to an `Employee` object. Otherwise, that would violate the the characteristic of a good `equals` function: "x.equals(y) should return true if and only if y.equals(x) returns true". – John Red Mar 08 '18 at 11:03
  • 3
    Yea, I appreciate the answer but on SO you really need to avoid assuming _why_ the OP is asking and suggesting they are doing something wrong. There are plenty of valid cases for this need. – Michael Peterson Aug 22 '20 at 02:25
8

If you are looking for exact class match the only means is qux.getClass().equals(Foo.class). instanceof will also return true for subclasses.

nitegazer2003
  • 1,193
  • 5
  • 10
5

you should use instanceof

if(qux instanceof Foo && !(qux instanceof Bar)) {
    ...
}

This works with both classes and interfaces, so in most cases it should preferred over .class which does not work with interfaces.

Marco Forberg
  • 2,634
  • 5
  • 22
  • 33
  • 3
    This won't catch the situation where `Baz` is a subclass of `Foo`. – Duncan Jones May 22 '13 at 09:54
  • is that so? the rhs of the `&&` should return false for instances of `Bar` no matter what other classes it extends – Marco Forberg May 22 '13 at 09:56
  • 1
    Assume `Baz` is a direct subclass of `Foo`. Both sides of your `if` clause will then evaluate to `true`. – Duncan Jones May 22 '13 at 09:59
  • you do see the `!`, do you? – Marco Forberg May 22 '13 at 10:00
  • 1
    Yes, I do. `Baz` is not an instance of `Bar` in my example. Note that I'm slightly extending the OP's original example to discuss the general case. – Duncan Jones May 22 '13 at 10:00
  • okay misunderstood the OP. Thought he wanted to rule out just a single subclass and let the other subclasses still behave just like the base class and i still don't know why one should want to do it this way – Marco Forberg May 22 '13 at 10:03
  • Upvoting this answer since as currently worded the question is ambiguous whether the OP is asking about the specific `Bar` subclass of `Foo` or any subclass of `Foo`. "its" in "but not a instance of its subclass of foo" doesn't really tell me if they mean "any subclass" or "the specific subclass I'm about to mention". – M. Justin Mar 23 '21 at 22:32
2

I just tried following code, it seems like working fine

public class BaseClass {

    private String a;

    public boolean isInstanceOf(BaseClass base){
        if(base == null){
            return false;
        }
        else if(getClass() == base.getClass()){
            return true;
        }else{
            return false;
        }
    }

}



public class DervidClass extends BaseClass {


    public boolean isInstanceOf(DervidClass base) {
        if(base == null){
            return false;
        }
        else if(getClass() == base.getClass()){
            return true;
        }else{
            return false;
        }
    }


}

public class myTest {
public static void main(String[] args) throws ParseException {


        BaseClass base = new BaseClass();
        BaseClass base1 = new BaseClass();
        DervidClass derived = new DervidClass();

        BaseClass d1 = new DervidClass();

        System.out.println(base.isInstanceOf(d1));
        System.out.println(d1.isInstanceOf(d1));
        System.out.println((d1 instanceof BaseClass));


    }
Karthik Prasad
  • 9,662
  • 10
  • 64
  • 112
2

I have read all the answers which have been posted so far but couldn't find satisfactory answer yet. Answering to Is there some kind of statement like instanceof for this check? or I should use qux.getClass().equals(Foo.class) question I would say yes, there is instanceof operator in java to check if the object is instance of class. Below is an example-:

class Vehicle {

}

class Car extends Vehicle {

}

public class Research {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();

        if (vehicle instanceof Vehicle) {
            System.out.println("vehicle instanceof Vehicle : TRUE");
        } else {
            System.out.println("vehicle instanceof Vehicle : FALSE");
        }

        if (vehicle instanceof Car) {
            System.out.println("vehicle instanceof Car : TRUE");
        } else {
            System.out.println("vehicle instanceof Car : FALSE");
        }

        System.out.println();
        Car car = new Car();

        if (car instanceof Vehicle) {
            System.out.println("car instanceof Vehicle : TRUE");
        } else {
            System.out.println("car instanceof Vehicle : FALSE");
        }

        if (car instanceof Car) {
            System.out.println("car instanceof Car : TRUE");
        } else {
            System.out.println("car instanceof Car : FALSE");
        }
    }
}

Output-:

vehicle instanceof Vehicle : TRUE
vehicle instanceof Car : FALSE

car instanceof Vehicle : TRUE
car instanceof Car : TRUE

Description-:instanceof operator tells if an object is a instance of a class or it's parent classes (up to any level).
vehicle instanceof Car : FALSE line of output is indicating that instanceof operator will not tell if an object is a instance of its sub class.

Another way is to use getClass().equals(Foo.class) to determine if an object is a instance of a class or not. Let us see below example-:

class Vehicle {

}

class Car extends Vehicle {

}

public class Research {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();

        if (vehicle.getClass().equals(Vehicle.class)) {
            System.out.println("vehicle instanceof Vehicle : TRUE");
        } else {
            System.out.println("vehicle instanceof Vehicle : FALSE");
        }

        if (vehicle.getClass().equals(Car.class)) {
            System.out.println("vehicle instanceof Car : TRUE");
        } else {
            System.out.println("vehicle instanceof Car : FALSE");
        }

        System.out.println();
        Car car = new Car();

        if (car.getClass().equals(Vehicle.class)) {
            System.out.println("car instanceof Vehicle : TRUE");
        } else {
            System.out.println("car instanceof Vehicle : FALSE");
        }

        if (car.getClass().equals(Car.class)) {
            System.out.println("car instanceof Car : TRUE");
        } else {
            System.out.println("car instanceof Car : FALSE");
        }


    }
}

Output-:

vehicle instanceof Vehicle : TRUE
vehicle instanceof Car : FALSE

car instanceof Vehicle : FALSE
car instanceof Car : TRUE

Description-: It would be clear from the above example that which one(out of above two) should be opted where?

Important Notes-:

  1. instanceof operator will not throw NullPointerException exception in case if reference variable is not pointing to any object(i.e. its having null reference).
  2. car.getClass().equals(Car.class) will throw NullPointerException exception in case if car is not pointing to any object(i.e. its having null reference). Therefore one must place extra null check with this for example car != null && car.getClass().equals(Car.class) to prevent it from NullPointerException.
  3. instanceof operator tells if an object is a instance of a class or it's parent classes (up to any level).
  4. car.getClass().equals(Car.class) will tell if an object is a instance of class only. (Parent & Sub classes will not be considered at all)
Ashish Kumar
  • 916
  • 2
  • 15
  • 32
1
    package com.instance;

    public class Foo {
        public void instance(Foo f) {
            System.out.println("---------");
            System.out.println(f.getClass());
            System.out.println(getClass());
            if (f.getClass() == getClass()) {
                System.out.println("Yes");
            } else {
                System.out.println("No");
            }
        }
    }


package com.instance;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Foo f1 = new Foo();
        Foo f2 = new Foo();
        Foo f3 = new Bar();
        f1.instance(f1);
        f1.instance(f2);
        f1.instance(f3);
    }

}
boiledwater
  • 10,372
  • 4
  • 37
  • 38
0

Well you already know that qux is instanceof Foo (unless it's null...), so a simple qux instanceof Bar and a null check should be all you need.

vikingsteve
  • 38,481
  • 23
  • 112
  • 156