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