简体   繁体   中英

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM