我是一名 Java 初学者,无法理解代码中
System.out.println(((A)b).s)
的输出。
我的理解是,静态变量可以在类中的任何位置更改,因此我希望其值为 2。在研究代码后,我发现静态变量有两个值
s
...为什么这是这样发生这种情况,既然名称和类型相等,就不应该引用同一个变量吗?
import java.util.ArrayList;
import java.util.List;
class A {
static int s;
int o;
A(int i) { o = i; s = i + 1;
System.out.println("A constructor called! String s is:" + s);
}
int m(int i) { return i; }
@Override
public String toString() { return String.format("A2S: %d %d" , o, s); }
}
class B extends A {
int o;
B(int i) { super(i); o = i; }
@Override
int m(int i) { return i + s; }
@Override
public String toString() { return String.format("B2S: %d %d", o, s); }
}
class C extends A {
static int s;
int o;
C(int i) { super(i); o = i; s = i - 1;
System.out.println("C constructor called! String s is:" + s);}
@Override
int m(int i) { return i + s; }
@Override
public String toString() { return String.format("C2S: %d %d", o, s); }
}
class D extends C {
int o;
D(int i) { super(i); o = i; }
@Override
int m(int i) { return i + o + s; }
@Override
public String toString() { return String.format("D2S: %d %d", o, s); }
}
public class Question {
public static void main(String[] args) {
int o = 1;
B b = new B(7);
System.out.println(b);
C c = new C(5);
System.out.println(c);
D d = new D(3);
System.out.println(d);
System.out.println(((C)d).o);
System.out.println("This is the s: " + b.s);
System.out.println("This is the s: " + c.s);
System.out.println("This is the s: " + d.s);
System.out.println(((A)b).s);
System.out.println(((A)d).m(o));
}
}
s
中的声明A
声明了与s
中的C
声明不同的变量。 是的,它们是具有相同(简单)名称的不同变量s
。
当您使用名称
s
时,其含义取决于您在何处使用它。
A
中,简单名称 s
与 A.s
指的是同一事物。B
中,简单名称s
指的是A.s
。 该名称继承自 A
的命名空间。C
中,简单名称s
现在指的是在s
中声明的C
;即 C.s
。D
中,简单名称s
也指从C.s
命名空间继承的C
。从技术上讲,在
s
中声明的变量 A
被 s
中声明的 C
隐藏。 这也适用于
D
。
这都是Java语言规范中规定的。
这就是为什么你的代码会有这样的行为。
为什么会发生这种情况,既然名称和类型相等,就不应该引用同一个变量吗?
不。 这是不正确的。 你的直觉不正确。 有两个不同的
static
变量称为 s
。 他们的全名是A.s
和C.s
。
请注意,您可以将
A.s
称为 B.s
,将 C.s
称为 D.s
。 但不要这样做。 这样做是“不好的风格”,因为它很容易误导读者认为(比如说)B.s
是B
的静态变量。 事实并非如此。
在此:System.out.println(((A)b).s);
您引用
s
的语法使得
s
看起来是实例变量。 实际上这是指静态变量A.s
。 事实上,以下所有内容都会打印该变量:System.out.println(A.s);
System.out.println(B.s);
System.out.println(a.s); // 其中 a
是类型为
A
的变量
System.out.println(b.s); // 其中 b
是类型为 B
的变量
System.out.println(((A)b).s);但只有第一个才是好的风格。 其他的都以某种方式产生误导,应该避免。