Curious cases of up-casting

106 views
Skip to first unread message

zhong...@gmail.com

unread,
Jul 22, 2015, 9:09:58 PM7/22/15
to java.lang.fans
An explicit up-cast converts a type to a supertype, for example, to cast an `Integer` to `Number`.

This is quite curious though. Ideally, a subtype should be implicitly usable as any of its supertypes. Although up-casting is obviously safe, and it should be allowed, is it actually needed anywhere? The answer is yes, and this thread collects cases where up-casting is needed.


zhong...@gmail.com

unread,
Jul 22, 2015, 9:31:54 PM7/22/15
to java.lang.fans, zhong...@gmail.com, zhong...@gmail.com
[up-cast case] To disambiguate varargs call

If we have a varargs method

    void foo(Object... args)

and we invoke it with an array

    String[] array = {"a", "b"};
    foo(array);

we'll get a compiler warning, because it is not obvious whether `array` is treats as `Object... args`, or as a single `Object` arg in args, since `String[]` is subtype of bother `Object[]` and `Object`.

The spec is quite clear on this matter, i.e. `array` is the whole `args`; but it might be confusing for human coders, hence the warning. The suggested solution is to explicitly cast it to `Object[]` or `Object` to make the programmer's intent clear

    foo( (Object[]) array );
    foo( (Object) array );

Paul Bellora

unread,
Jul 22, 2015, 9:36:12 PM7/22/15
to zhong...@gmail.com, java.lang.fans
Let's say there are a class Parent and its subtype Child. If a method declared in Parent works on an object of type Child, it will need to upcast it to Parent in order to access its own private members. This is because visibility of private members isn't inherited.

Taken from this post which deals with the same dilemma for parameterized types.

--
You received this message because you are subscribed to the Google Groups "java.lang.fans" group.
To unsubscribe from this group and stop receiving emails from it, send an email to java-lang-fan...@googlegroups.com.
To post to this group, send email to java-la...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/java-lang-fans/4e26e300-9cec-4387-9095-a5033488df6f%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

zhong...@gmail.com

unread,
Jul 22, 2015, 9:41:30 PM7/22/15
to java.lang.fans, zhong...@gmail.com, zhong...@gmail.com
[up-cast case] For cross-casting

Suppose we have a `Supplier<Integer>`, and an API requires a `Supplier<Number>` (without wildcard), we want to take the lazy route, and just brutely cast `Supplier<Integer>` to `Supplier<Number>`. We know this works due to erasure and it is perfectly safe at runtime. However, the compiler will not allow that, because it is obviously not type safe.

To fool the compiler, we can do an up-cast, then do a down-cast.

    Supplier<Integer> x = ...;
    Supplier<Number> y = (Supplier<Number>)(Supplier<?>)x;

Of course, we can always use (Object) for the upcast, to cast between any two times. But it might be a good form to use a supertype that is closer to both types.

zhong...@gmail.com

unread,
Jul 22, 2015, 9:56:22 PM7/22/15
to java.lang.fans, zhong...@gmail.com, zhong...@gmail.com
[up-cast case] Parent private members

(expanding on Paul Bellora's post)

A private member is accessible thoughout the entire body of the top level class it is declared in.

public class Top
{
    static class A
    {
        private int x = 1;
    }

    static class B
    {
        void foo(A a)
        {
            print(a.x);  // access A's private member
        }
    }

Here, `B` can access `A.x`, a private member of `A`, because they are both in the same top level class `Top`.

On the other hand, private members are excluded from inheritance, regardless of access rights

    static class C extends A   // within the same top level class
    {
        void bar()
        {
            print(this.x); // error, there is no member `x` in `C`
        }

We need to cast a `C` to `A` where the private member is declared to access the member

        void bar()
        {
            A a = (A)this;
            print(a.x);
        }

zhong...@gmail.com

unread,
Jul 22, 2015, 10:15:19 PM7/22/15
to java.lang.fans, zhong...@gmail.com, zhong...@gmail.com
[up-cast case] - Cast a type variable to its upper bound for capture conversion

Consider this example:

    <X extends List<?>> void foo(Class<X> clazz) throws Exception
    {
        List<?> instance = clazz.newInstance();
        bar(instance);
    }

    <T> void bar(List<T> list) { ... }

We know that capture conversion is done in expression `b(instance)` - the type of `instance`, `List<?>`, is converted to `List<W>` for some unknown type W; then `T` in `bar()` is infer as `T=W`.

The return type of `clazz.newInstance()` is actually `X`, the type variable with upper bound `List<?>`. However, this won't work -

        X instance = clazz.newInstance();
        bar(instance);

because according to spec, capture conversion only applies to wildcard parameterized types; on any other type, (e.g. `X` here), the type is left as is.

Now type inference fails on `bar(instance)`, because it cannot find a `T` so that `X` is a subtype of `List<T>`.

This problem can be viewed as a flaw of the spec; the workaround is to cast the type variable to the upper bound so that capture conversion can be applied -

        X instance = clazz.newInstance();
        bar( (List<?>) instance );

--
Zhong Yu
bayou.io

zhong...@gmail.com

unread,
Jul 22, 2015, 10:24:46 PM7/22/15
to java.lang.fans, bell...@gmail.com, bell...@gmail.com


On Wednesday, July 22, 2015 at 8:36:12 PM UTC-5, Paul Bellora wrote:
Let's say there are a class Parent and its subtype Child. If a method declared in Parent works on an object of type Child, it will need to upcast it to Parent in order to access its own private members. This is because visibility of private members isn't inherited.

Yes. This case is also valid prior to java 5, unlike my other cases.

It is curious to include up-cast in the language design in the 1st place; aside from aesthetic reason, I wonder if there were other use cases in earlier Java that required explicit up-cast.

Zhong Yu
bayou.io

Zhong Yu

unread,
Jan 12, 2016, 8:55:33 PM1/12/16
to java.lang.fans
[up-cast case] - a parent member is hidden by the child class

    class Parent
    {
        String x = "x";
    }

    class Child extends Parent
    {
        boolean x = true;
    }

Given a `Child` instance, we need to cast it to `Parent` to access `x` of `Parent`.


Zhong
Reply all
Reply to author
Forward
0 new messages