Inheritance rules in java

陌路散爱 提交于 2020-08-19 07:45:09

问题


I have a question about the basics of java. I have the s attribute in each class. The value of s gotten by the instance of the class is different when I use the accessor (getS()). Is there a rule for this case?

The output of the main is :

x.s  = One
x.getS()  = Three

The classes definition :

package com;

import com.Test1.A;
import com.Test1.B;

public class Test1 
{
    public static class A 
    {
        public static String s = "One";
        public int x = 10;

        public String getS() 
        {
            return this.s;
        }
    }

    public static class B extends A 
    {
        public final String s = "Two";
        public String getS() 
        {
            return this.s;
        }
    }

    public static class C extends B 
    {
        public static int x = 1;
        public static String s = "Three";

        public String getS() 
        {
            return this.s;
        }
    }

    public static void main(String [] args) 
    {

        A x = new C();
        System.out.println("x.s  = "+x.s);
        System.out.println("x.getS()  = "+x.getS());
    }
}

回答1:


The access of the field (x.s) is resolved through the compile-time type of x (which is A, so A's x ["One"] is returned).

The access through the getter (x.getS()) is resolved through the runtime type of x (which is C, so C's x ["Three"] is returned).

Some other examples:

  • ((B) x).s will return "Two"
  • ((C) x).s will return "Three"
  • ((A) x).getS() will return "Three"
  • ((B) x).getS() will return "Three"

(I leave the why as an exercise for the reader)

As an aside: the result does not change when

  • static is removed from String s = "One" in A, or
  • method public String getS() is removed from classes B and C, or
  • both of the above

Please read @Mike Nakis' answer as well.

One final remark on the code: the import-statements can be removed.




回答2:


The static keyword in front of your variables probably isn't what you intended and it pushes you into a weird corner of Java's semantics.

Here's what you probably intended:

public class Test1 {
  public static class A {
    public String s = "One";
    public int x = 10;

    public String getS() {
      return this.s;
    }
  }

  public static class B extends A {
    public B() {
      this.s = "Two";
    }

    public String getS() {
      return this.s;
    }
  }

  public static class C extends B {
    public C() {
      this.s = "Three";
    }

    public String getS() {
      return this.s;
    }
  }

  public static void main(String[] args) {
    A x = new C();
    System.out.println("x.s  = " + x.s);
    System.out.println("x.getS()  = " + x.getS());
  }
}

This prints

x.s  = Three
x.getS()  = Three

as you'd expect.


The main difference between what you wrote and what I wrote is that without the static, we're declaring that every A has an s field; with static, we're saying that the concept of A-ness has an associated s idea. This is useful in some limited circumstances (for instance, the Java Integer class has a static field called MAX_VALUE because the maximum possible integer is associated with the concept of integers; every integer doesn't have its own individual max value), but it's probably not the first concept you want to learn.




回答3:


There are, of course, rules for everything.

The expression x.s is problematic, because you are accessing a static field via an instance reference, and the compiler / IDE should have been issuing a warning for it. So, what this is telling me is that you are probably trying to compile java without important warnings enabled. Don't do that, if this way you go, only pain you will find. Read up on how to enable warnings on your compiler / IDE and enable as many of them as you possibly can.

The fix for the warning would be to replace x.s with A.s, and that would make clear exactly what is happening.

The s attribute that you are speaking of (more commonly referred to as 'field' in the java world) has been declared as static in some cases, but non-static in one case, and this does not look intentional. Generally, static is to be used only in very special cases, don't use it if you do not have a very good reason for doing so.

Also, some fields are final, some aren't, and this does not look intentional, either. You need to be very careful with these things.

Other than that, Turing85's answer basically covers it.



来源:https://stackoverflow.com/questions/57244660/inheritance-rules-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!