Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java polymorphism and downcasting

I am playing with Java's reflection API, and I'm writing methods that inspect a given object and describes its fields, methods, and so on.

I am using the getFields() method to iterate on the different attributes and display the object contents:

public static void display(Integer i)
{
    System.out.println("An integer: " + i);
}

// Basically a method for each primitive type wrapper

public static void display(Object o)
{
    for (Field f : c.getFields())
    {
        System.out.println("A " + o.getClass() + " which is composed of:");
        display(f.get(o));
    }
}

(Other primitive types and arrays omitted for simplicity's sake.)

Eventhough Field's get method returns an Object, I thought the right methods would be called for the primitive type wrappers (Integers, Strings, etc.), but actually, only display(Object o) is called (no implicit downcasting is performed).

For now, the only solution I have found is to brutally downcast the objects if possible like this:

public static void display(Object o)
{
    if (o instanceof Integer)
    {
        display((Integer) o);
        return;
    }
    else if (o instanceof String 
    {
        ... 
    } // And so on

    for (Field f : c.getFields())
    {
        System.out.println("A " + o.getClass() + " which is composed of:");
        display(f.get(o));
    }
}

This does however seem ugly, and I was wondering if there was a more elegant way to make sure the right method is called. Any ideas?

Thanks in advance, good people from StackOverflow!

like image 744
executifs Avatar asked Jun 13 '11 17:06

executifs


People also ask

Is downcasting possible in Java?

In Java, the object can also be typecasted like the datatypes. Parent and Child objects are two types of objects. So, there are two types of typecasting possible for an object, i.e., Parent to Child and Child to Parent or can say Upcasting and Downcasting.

What does downcasting mean in Java?

Downcasting: Similarly, downcasting means the typecasting of a parent object to a child object.

What is difference between Upcasting and downcasting in Java?

Upcasting (Generalization or Widening) is casting to a parent type in simple words casting individual type to one common type is called upcasting while downcasting (specialization or narrowing) is casting to a child type or casting common type to individual type.

What is downcasting in oops?

In class-based programming, downcasting or type refinement is the act of casting a reference of a base class to one of its derived classes.


2 Answers

Good question. I was wondering yesterday night too ;)

So the answer is that there are 2 different types of polymorphism : compile-time and run-time polymorphism.

When you use a method of a supertype and the overriden methods of sybtypes, this is run-time polymorphism.

When you use a super types and sub types as parameters for different overloaded methods, this is compile-time polymorphism.

So the compiler, in your case, has to know at compile-time which method(/overload) to execute, it won't take this decision at run-time.

If you would have Control over the field class, then a solution would be to use generics so that you define a

class Field<T> 

with a method

T get( Object o )

Then the compiler would be able to know, at compile time, which method to use for display as it would know, at compile-time, what type is returned by field.get.

But, according to your comments, you use the JDK's class java.lang.reflect.Field and thus, you have no control over it to make it generic. In this case, yes, the only solution is to have a display method that handles all the different possible types for field.get. But indeed, the String.valueOf method could greatly help here as it provides a string representation of any type in java, already does the overload job you are looking for.

Source here.

Regards, Stéphane

like image 109
Snicolas Avatar answered Sep 25 '22 21:09

Snicolas


What you want is so called "double dispatch" which Java doesn't support.

You can simulate it through reflection: check all your display methods and their argument types, and dynamically invoke one of them based on the runtime type of an object.

That is unnecessarily clever for this problem. Your if-else chain is just fine.

like image 35
irreputable Avatar answered Sep 22 '22 21:09

irreputable