Acces to private field from nested class when the type of reference is a generic type variable with upper bound of outer class
Peter Levart
peter.levart at gmail.com
Sat Oct 8 03:25:02 PDT 2011
On Saturday, October 08, 2011 12:37:48 AM Dan Smith wrote:
> 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'.
Ok I understand that now. To resolve this, field access would have to be dynamic at runtime
(similar to virtual methods dispatch) and that is not an option for Java.
>
> 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.
Ok, that's clear now too. I misinterpreted the type-variables. Now that I have read the
chapters 4.4 and 4.9 in JLS once more, I see that type-variable <T extends A> in our situation
has the following analogue situation without using type variables:
public class A { public int field; }
public class T extends A {}
public class B extends A { public int field; }
Therefore T.field resolves to A.field.
And using this analogue (and knowing that by definition T is in the same package as A) it's now
more clear which fields are accessible and which not via type-variable typed variables.
Thanks,
Peter
>
> —Dan
More information about the compiler-dev
mailing list