17

Is there a way to find out the name of derived class from a base class instance?

e.g.:

class A{
    ....
}
class B extends A{
    ...
}
class c extends A{
    ...
}

now if a method returns an object of A, can I find out if it is of type B or C?

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
Vaishak Suresh
  • 5,735
  • 10
  • 41
  • 66
  • 9
    Note that [type sniffing](http://www.javapractices.com/topic/TopicAction.do?Id=3) is a bit of a code smell. It's not always the wrong thing to do, but it is the wrong approach often enough that you should take a close look at your design. If possible, rely on polymorphism (but see also Steve Yegge's [When Polymorphism Fails](http://sites.google.com/site/steveyegge2/when-polymorphism-fails)). – outis May 18 '10 at 09:57
  • baseInstance.getClass().getName() – paiego Sep 02 '20 at 21:51

7 Answers7

25

using either instanceof or Class#getClass()

A returned = getA();

if (returned instanceof B) { .. }
else if (returned instanceof C) { .. }

getClass() would return either of: A.class, B.class, C.class

Inside the if-clause you'd need to downcast - i.e.

((B) returned).doSomethingSpecificToB();

That said, sometimes it is considered that using instanceof or getClass() is a bad practice. You should use polymorphism to try to avoid the need to check for the concrete subclass, but I can't tell you more with the information given.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 1
    A note on using polymorphism in this situation: You could have a method `getType()` or something similar in the implementation of `A` and override that method in `B` and `C`. Since all methods are virtual in java, a call to `getType()` would resolve the specific subtype. – aioobe May 18 '10 at 10:26
5

Have you tried using instanceof

e.g.

Class A aDerived= something.getSomethingDerivedFromClassA();

if (aDerived instanceof B) {

} else if (aDerived instanceof C) {

}

//Use type-casting where necessary in the if-then statement.
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
4

Short answer to your question

Is there a way to find out the derived class's name from a base class object?

no, the super-class has no way of telling the name/type of a sub-class.

You have to interrogate the object (which is an instance of a sub-class) and ask if it is an: instanceof a particular sub-class, or call it's getClass() method.

Timothy
  • 2,457
  • 19
  • 15
2

You can do it in the subclass' constructor

class A {
    protected String classname;
    public A() { this.classname = "A"; }
    public String getClassname() { return this.classname; }
}
class B extends A {
    public B() {
        super();
        this.classname = "B";
    }
}

So

A a = new A();
a.getClassname(); // returns "A"
B b = new B();
b.getClassname(); // returns "B"
((A)b).getClassname(); // Also returns "B"

Because it is casted into an "A" object, it will call the "A" getClassname() function but will return a value set by the constructor that was the "B" constructor.

Note: Call super(); before setting it

user3071284
  • 6,955
  • 6
  • 43
  • 57
0

There are 2 ways I can think of 1) One with Using the Java reflection API 2) Other one would be with the instanceOf

Other method can be a Comparing objects to objects, I dont know how it might be, you can try this

gmhk
  • 15,598
  • 27
  • 89
  • 112
0

Is there a way to find out the name of derived class from a base class instance?

As answered here, you can use this extremely simple approach.

abstract class A {
    public final String getName() {
         return this.getClass().getName();
    }
}

class B extends A { }

class C extends A { }

then simply print the current class name:

B b = new B();
C c = new C();

System.out.println(b.getName());
System.out.println(c.getName());

Output:

com.test.B
com.test.C

There is no need to store additional Strings, check instanceof or override the method in any subclass.

payloc91
  • 3,724
  • 1
  • 17
  • 45
0

A more modern approach (Java 16+) would be using pattern matching for the instanceof operator. The syntax is pretty simple:

if(x instanceof X xChild){
    // use xChild
}

It is both shorter and less error-prone as it combines all the steps of testing the runtime type of the variable(x in the example above), casting it down, and assigning it to a new variable(`xChild in the example above). Read more.

Another example:

    public void addUIControl(UIControl control) {
        if(control instanceof SelectList sl){
            selectList = sl;
        }
        else if(control instanceof TextBox tb){
            textBox = tb;
        }
        else if(control instanceof Button btn){
            button = btn;
        }
        else {
            throw new IllegalArgumentException("Uknown UIControl object has been passed to the SendFormMediator");
        }
    }
aderchox
  • 3,163
  • 2
  • 28
  • 37