ankush981
ankush981

Reputation: 5417

getClass() returns derived class name after upcasting

I've come across a weird thing while learning Java. Consider the following program:

public class GetClassNameInheritance {
    public static void main(String[] args) {        
        Employee e = new Employee();
        Person p = (Person) e;
        System.out.println(p.getClass());
    }
}

class Person {

}

class Employee extends Person {

}

I was expecting the output to be Person because of the cast, but it is Employee! Honestly, I'm stumped and can't find an explanation. The official Oracle tutorial doesn't mention this behavior, and the docs seem too terse to be helpful. I can make out from other StackOverflow examples that this is something to do with "runtime class" but I don't understand the underlying idea. Can someone explain what's going on here?

Upvotes: 1

Views: 1370

Answers (3)

Mritunjay
Mritunjay

Reputation: 25892

If you want to know the super class of current class, you can use

p.getClass().getSuperclass() //returns person.

From the docs

getClass() always returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.

And a runtime class is one which has been instantiated with the constructor call.

Actually, if you will see, here Person p = (Person) e; the cast is not needed, you can always assign a derived class object to a base class.

For Example

List<String> list = new ArrayList<>();

Above will not throw an error.

Upvotes: 0

Display Name
Display Name

Reputation: 952

Well let's look what happens when the main method is compiled:

     0: new           #2                  // class Employee
     3: dup           
     4: invokespecial #3                  // Method Employee (Constructor)
     7: astore_1                          // Save local variable "e"
     8: aload_1                           // Load local variable "e"  
     9: astore_2                          // Save to local variable "p"
    10: getstatic     #4                  // Field System.out PrintStream;
    13: aload_2                           // Load local variable "p"
    14: invokevirtual #5                  // Method Object.getClass()
    17: invokevirtual #6                  // Method PrintStream.println(Object)

And if we were to look at a decompiler's interpretation of this bytecode:

public static void main(String[] args) {
    Employee e = new Employee();
    System.out.println(e.getClass());
}

The compiler has "optimized" the code which results in your cast being removed since it was deemed unnecessary. Anacron's answer explains why the compiler deemed it unnecessary.

Upvotes: 1

anacron
anacron

Reputation: 6721

In Java, Type casting does not change the type of object. Once an Employee, your object is always an Employee. Type casts do not work like in other languages such as C/C++.

Though the p reference is of type Person, it is in fact referring to an object of type Employee in the JVM heap. When you invoke the p.getClass() method, the reference in turn invokes the method on the object and not on the reference. That's the reason you see Employee in your output.

The only type of casts that would work is the one that you can perform on primitives.

int x = (int)2.5f;

The return value will be type cast to int.

You can read more about type casts and conversions here:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

http://www.wideskills.com/java-tutorial/java-object-typecasting

Upvotes: 3

Related Questions