import java.lang.reflect.*;

/**
 * This illustrates some really flakey inner class stuff
 * such as the bizarre new syntax when you are out of the class,
 * overusing the same name,
 * and the use of reflection to access the package private member.
 * Don't try this in real code!
 */
class Outer
{
    private int x;
    
    public Outer( int x )
    {
        this.x = x;
    }
    
    // This is really stupid
    // No point making it public
    // And can't we think of a better name than x?
    public class Inner
    {
        private int x = 37;

        public int getX( )
        {
            return x;
        }
        
        public int getOuterX( )
        {
            return Outer.this.getX( );
        }
        
        // This method is here to show real nonsense.
        // Since Outer.this.x is private, compiler
        // generates a static wrapper that returns its value.
        // signature will be int return type Outer as param.
        // Name we don't know exactly; happens to be access$000.
        public int getOuterXDirect( )
        {
            return Outer.this.x;
        }
    }

    public int getX( )
    {
        return x;
    }
}

class NonsenseDemo
{
    public static void main( String[] args )
    {
        Outer out = new Outer( 100 );
        System.out.println( "Using normal access through out ref" );
        System.out.println( "Outer's x is " + out.getX( ) );
        
        Outer.Inner in = out.new Inner( );
        System.out.println( "Using normal access through in ref" );
        System.out.println( "Inner's x is " + in.getX( ) );
        System.out.println( "Outer's x is " + in.getOuterX( ) );

        Class outerClass = Outer.class;
        
        try
        {
                // Use reflection to invoke the accessor wrapper for private x
            Method wrapper = outerClass.getDeclaredMethod( "access$000",
                                                    new Class[] { outerClass  } );
            Object value = wrapper.invoke( null, new Object[]  { out } );
            System.out.println( "Using reflection and hidden accessor" );
            System.out.println( "Outer's x is " + value );
        }
        catch( Exception e )
        {
            e.printStackTrace( );
        }
    }
}
        
        

