Acces to private field from nested class when the type of reference is a generic type variable with upper bound of outer class
Dan Smith
daniel.smith at oracle.com
Fri Oct 7 15:37:48 PDT 2011
On Oct 7, 2011, at 2:54 PM, Peter Levart wrote:
> And now for some puzzlers. Let's take that definition and a look at the following program:
>
>
> package test;
>
> public class Test
> {
> public static class A
> {
> public int field = 1;
> }
>
> public static class B extends A
> {
> public int field = 2;
> }
>
> public static class FieldGetter<T extends A>
> {
> public int getField(T obj)
> {
> return obj.field;
> }
> }
>
> public static void main(String[] args)
> {
> A a = new A();
> B b = new B();
>
> FieldGetter<A> aFieldGetter = new FieldGetter<A>();
> FieldGetter<B> bFieldGetter = new FieldGetter<B>();
>
> System.out.println(a.field); // 1
> System.out.println(b.field); // 2
>
> System.out.println(aFieldGetter.getField(a)); // 1
> System.out.println(aFieldGetter.getField(b)); // 1
>
> System.out.println(bFieldGetter.getField(b)); // 1 !!!
> }
> }
>
>
> ... in FieldGetter the T is the most general type that is a subtype of A and any subtypes of A
> (which includes B). Now A.field is inherited by any subtypes of A, but it can also be hidden by
> fields of the same name in any of the subtypes of A (as is in the example by B.field).
>
> The question is: How can compiler decide which field to access in T.getField method?
>
> Would it be right to disallow "any" field access via the type-variable typed variables?
>
> The joys of erasure!
This isn't a consequence of erasure. It's a consequence of static field resolution (in contrast to dynamic resolution of methods). The class referenced by a field name is determined at compile time. Wouldn't matter if T were reified -- we'd still have to pick a field at compile time, and the only sound choice would be 'A.field'.
The fact that T is a type variable is, in a sense, irrelevant. Given class T extends A and class B extends T, the same problem arises -- when the receiver is "really" a B (at runtime), a user might wish that a reference to 'field' in type T resolve to 'B.field', but that's not the way field references work.
—Dan
More information about the compiler-dev
mailing list