问题
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).swill return"Two"((C) x).swill 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
staticis removed fromString s = "One"inA, or- method
public String getS()is removed from classesBandC, 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