5 Replies Latest reply: Sep 24, 2006 8:41 AM by 796254 RSS

    sth very strange about the field of super and subclass

    807598
      class Base{
      private String name;
      }

      public class Sub extends Base{
      public static void main(String[] agr){
      Sub s1 = new Sub();
      s1.name="wahaha";
      }
      }

      once compiled, the console shows:

      Sub.java:8: name has private access in Base
      s1.name="wahaha";
      ^
      1 error

      It seems like field "name" doesnt inherit from the Base class(if it does, s1.name should be accessible)

      However, using the following program:

      import java.lang.reflect.*;
      abstract class Base {
      private String name = "hello world";
      public void foo() {
      System.out.println(name);
      }
      }
      public class Sub extends Base {
      public static void main(String[] agr) throws Exception {
      Sub s1 = new Sub();
      //Field f = Base.class.getDeclaredField("name"); //it works
      Field f = Sub.class.getDeclaredField("name");
      f.setAccessible(true);
      s1.foo();
      f.set(s1, "wahaha");
      s1.foo();
      }
      }

      In runtime the concole shows:

      Exception in thread "main" java.lang.NoSuchFieldException: name
           at java.lang.Class.getDeclaredField(Unknown Source)
           at Sub.main(Sub.java:12)

      even if the name is changed to public, the same exception remains

      Does this mean, the fields in subclass just refers to those in corresponding superclass, with the fact that we can access the subclass field by using sth like sub.name = ... while this filed is public or other accessible properties?
        • 1. Re: sth very strange about the field of super and subclass
          796254
          class Base{
          private String name;
          }

          public class Sub extends Base{
          public static void main(String[] agr){
          Sub s1 = new Sub();
          s1.name="wahaha";
          }
          }

          once compiled, the console shows:

          Sub.java:8: name has private access in Base
          s1.name="wahaha";
          ^
          error

          It seems like field "name" doesnt inherit from the
          Base class(if it does, s1.name should be accessible)
          Wrong. It does inherit from Base, but access to name is private - even to children. If that were not so, you could break encapsulation anytime you wanted to just by inheritiing a class.

          If Base wants to expose name to subclasses, it can do so either by explicitly offering get/set methods OR by making it protected. Go back and read what protected access means.
          However, using the following program:

          import java.lang.reflect.*;
          abstract class Base {
          private String name = "hello world";
          public void foo() {
          System.out.println(name);
          blic class Sub extends Base {
          public static void main(String[] agr) throws
          Exception {
          Sub s1 = new Sub();
          //Field f = Base.class.getDeclaredField("name");
          //it works
          Field f =
          Sub.class.getDeclaredField("name");
          f.setAccessible(true);
          s1.foo();
          f.set(s1, "wahaha");
          s1.foo();
          }
          runtime the concole shows:

          Exception in thread "main"
          java.lang.NoSuchFieldException: name
               at java.lang.Class.getDeclaredField(Unknown Source)
               at Sub.main(Sub.java:12)

          even if the name is changed to public, the same
          exception remains

          Does this mean, the fields in subclass just refers to
          those in corresponding superclass, with the fact that
          we can access the subclass field by using sth like
          sub.name = ... while this filed is public or other
          accessible properties?
          No.

          Sub doesn't declared any such field. In both cases, the JVM is telling you the truth. Why don't you believe it?

          This is a classic example of "check your assumptions". You are assuming certain behavior on the part of the JVM when it comes to inheritance. Your assumptions contradict the behavior you observer. So - check your assumptions.

          %
          • 2. Re: sth very strange about the field of super and subclass
            807598
            class Base{
            private String name;
             }
            
            public class Sub extends Base{
            public static void main(String[] agr){
            Sub s1 = new Sub();
            s1.name="wahaha";
            you can't access private variables, you can however indirectly access them such as here:
            class Base{
            private String name;
             
            public void setName(String name)
            {
                 this.name=name; 
            }
            
            public class Sub extends Base{
            public static void main(String[] agr){
            Sub s1 = new Sub();
            s1.setName("wahaha");
            your second code is intriguing to me. I have not tried that before. I'll check it out.

            null
            • 3. Re: sth very strange about the field of super and subclass
              807598
              hi, what I think is that the key is what extends("inherits") means, not private.

              class Sub2 {
                   private String name;
                   public static void main(String args[]) {
                        Sub2 s = new Sub2();
                        System.out.println(s.name);
                        s.name = "hello";
                        System.out.println(s.name);
                   }
              }

              class Base{
              private String name;
              }

              public class Sub extends Base{
              public static void main(String[] agr){
              Sub s1 = new Sub();
              s1.name="wahaha";
              }
              }

              Compared Sub with Sub2,
              It can be seen that Sub2 can access this private field(of course) because this field name is in class Sub2.
              However class Sub(derived from class Base with private name field) cannot access this name field. Why? All fields are inherited, even it is a private field it should be accessed because the private field belongs to the subclass.

              Perhaps, I should assume there are only public inheritance in Java?
              • 4. Re: sth very strange about the field of super and subclass
                800308
                Base.name is still there allright, you have inherited it, but IT'S STILL NOT YOURS TO PLAY WITH...

                if java worked according to your ideas there would be no way keep variables private... coz all any hack would have to do is extend your class to get access to all it's private bits... probably NOT a great design when for example, you're writing an encryption library class, and need somewhere to store a private key safely.

                Does That Make Sense Now?

                Keith.
                • 5. Re: sth very strange about the field of super and subclass
                  796254
                  the interesting bit that the OP points out is that you can always get access to private members using reflection. that's certainly true.

                  but what the jvm is telling him/her is quite literally correct: there is no field "name" declared for the class Sub. It is declared for the superclass Base.

                  Since java.lang.Class gives you access to every interface, subclass, and superclass that's pertinent, I'd suggest that the OP write the code to travel up the inheritance hierarchy until the superclass is equal to Object or null.

                  The erroneous assumption is that the JVM does this recursion for you. It does not.

                  %