Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4053194

problems with accessing inner classes private fields

XMLWordPrintable

    • x86, sparc
    • solaris_2.5.1, windows_95



      Name: laC46010 Date: 05/20/97



      JDK1.1.2E compiler allows to read private field of one inner class from
      another (sibling) inner class while JDK1.1 prohibits that.

      In the example "Test1" below, method testAccess() of inner class Test1.A
      prints out the private field 'p' of other sibling inner class Test1.B

      JDK1.1 reports the following compile-time error:

      Test1.java:9: Access across scopes to the private member p in inner class Test. B is not implemented. The reference will succeed if the member is given package scope.
      System.out.println("b.p="+b.p);
      ^
      1 error

      At the same time both JDK1.1.1 and JDK1.1.2E compile and execute Test1
      and print out correct value of that private field 'p' (153).

      Note that all considered compiler versions don't allow to write into private field
      in the same conditions - see "Test2" below for which JDK1.1.2E compiler reports:

      Test2.java:8: Invalid left hand side of assignment.
      b.p = 7;
      ^
      1 error

      It seems to be inconsistent that compiler allows reading but denies writing.
      "Inner Classes in Java 1.1" specification says:

      "Access protection never prevents a class from using any member
      of another class, as long as one encloses the other, or they
      are enclosed by a third class."

      There are ambiguities in this statement.

      First, it is not clear what is "one" and what is "other" in
      "as long as one encloses the other" phrase. We assume the following
      sense:

      "Access protection never prevents a class A from using any member
      of another class B, as long as B encloses A, or they are enclosed
      by a third class."

      Second, it is unclear, whether words "they are enclosed by a third class"
      mean C{A{B{}}} or C{A{}B{}} :

      -- if C{A{B{}}} assumed then the bug is that we can read private field
         of sibling inner class in C{A{}B{}} case;

      -- if C{A{}B{}} assumed then the bug is that we can't use it as a left
         hand side of assignment.


      --------------------Test1.java----------------------
      public class Test1 {
      public static void main(String argv[]) {
      new Test1().new A().testAccess();
      }
      class A {
      void testAccess() {
      B b = new B();
      System.out.println("b.p="+b.p);
      }
      }
      class B {
      private int p=153;
      }
      }
      --------------------Test2.java----------------------
      public class Test2 {
      public static void main(String argv[]) {
      new Test2().new A().testAccess();
      }
      class A {
      void testAccess() {
      B b = new B();
      b.p = 7;
      System.out.println("b.p="+b.p);
      }
      }
      class B {
      private int p=153;
      }
      }
      --------------------Test3.java----------------------
      public class Test3 {
      public static void main(String argv[]) {
      new Test3().new A().testAccess();
      }
      class B {
      class A {
      void testAccess() {
      }
      }
      }
      }
      ---------------------------------------------------------


      ======================================================================

      [chamness 5/21/97] Another user reports the same problem:

      From: Roly Perera

      Synopsis: Access across sibling scopes is read-only!

      Description: javac claims that the following field access expression is
      not a valid assignment target. However it is, because its value is a
      reference to a non-final field:

      class A {
          class B {
              private int x;
          }

          class C {
              { new B().x = 5; } // javac doesn't allow this
          }
      }

      ======================================================================

      [chamness 6/20/97] And another user reports the same problem:

      Name: Lee Hasiuk
      Synopsis: Anonymous Inner Class Compilation Bug in JDK 1.1.1

      Description:
      (Resubmitted since I never received an automated reply.)

      The code included in this message, below, will not compile with JDK 1.1.1 as long as exit() is declared private. The following compilation (bogus) errors are reported:

      AnonBug.java:18: Can't reference this before the superclass constructor has been
       called.
              addWindowListener(
                               ^
      AnonBug.java:23: Can't reference this before the superclass constructor has been
       called.
                          exit();
                              ^
      AnonBug.java:27: Can't reference this before the superclass constructor has been
       called.
              setVisible(true);
                        ^
      3 errors

      This appears to be a compiler bug, since inner classes are supposed to be able to call private methods of enclosing instances. I can make the adapter into a named inner class and it compiles just fine. I can also get it to compile by changing the access of exit() to package or public.

      Here's the code:

      import java.awt.*;
      import java.awt.event.*;

      public class AnonBug extends Frame
      {
          public static void main(String args[])
          {
              new AnonBug().init();
          }

          public AnonBug()
          {
              super("Anon Bug");
          }

          public void init()
          {
      addWindowListener(
      new WindowAdapter()
      {
      public void windowClosing(WindowEvent e)
      {
      exit();
      }
      }
      );
      setVisible(true);
          }

          private void exit()
          {
      System.exit(0);
          }
      }


            wmaddoxsunw William Maddox (Inactive)
            leosunw Leo Leo (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: