Mordechai
Mordechai

Reputation: 16284

Why is Multiple Type-Casting Required?

Consider the following hierarchy:

TopClass
      |__ MiddleClass
                  |__ BottomClass 

Then the following code is of-course not required:

public BottomClass getBottom() {
    return (BottomClass) (MiddleClass) getObject();
}

Where getObject() returns an instance of type BottomClass but has a return type of TopClass.

You could effectivily short-circuit it, and cast directly to BottomClass.


But this code raised my brows:

In the JavaFX source package, class: com.sun.javafx.scene.control.skin.ProgressIndicatorSkin

@Override
public StyleableProperty<Paint> getStyleableProperty(ProgressIndicator n) {
    final ProgressIndicatorSkin skin = (ProgressIndicatorSkin) n.getSkin();
        return (StyleableProperty<Paint>)(WritableValue<Paint>)skin.progressColor;
}

Where the interface hierarchy is:

WritableValue<T>
              |__ StyleableProperty<T>

And progressColor is of type StyleableObjectProperty<Paint>, that implements StyleableProperty<Paint>, but is stored in an ObjectProperty<Paint> variable, like this:

private ObjectProperty<Paint> progressColor = new StyleableObjectProperty<Paint>(null)

Any clue what's going on here?

Upvotes: 1

Views: 154

Answers (1)

ZhongYu
ZhongYu

Reputation: 19682

The intermediary cast seems unnecessary. Direct cast should work.

However, the direct cast would be a "cross" cast - casting between two types that has no apparent subtype relationship.

The programmer probably doesn't want that; instead, it's more comfortable for the programmer to upcast to a nearest common supertype, then do a downcast, which feels "safer".


Discussion of casts:

It's always safe to do an "up" cast

    (Animal)cat

It is allowed to do a "down" cast; the compiler assumes the programmer knows better about the actual runtime type

    (Cat)animal

It is the "cross" cast that is a problem. Sometimes it is obvious that the cross-cast is impossible

    (Cat)dog   // Cat and Dog are two classes, and no subclass relation

    (List<Cat>) listDog   //  List<Dog> => List<Cat>

    (Runnable)fish    // Fish is a final class that does not implement Runnable

However, if it is not provably incorrect, the compiler would allow it, trusting the programmer

     (Runnable)animal   // Animal class does not implement Runnable; but a subclass may

We can always cast between any two types by going through a common supertype

     (List<Cat>)(List<?>) listDog

Of course, Object is the common supertype of all types, so we can use it to force any casts

     (Cat)(Object)dog

Upvotes: 1

Related Questions