静态变量在初始化对象本身之前为空
Static Variables are null before initializing the object itself
今天我 运行 关注以下问题:
我有三个 classes,(superclass) A,(subclass) B 和我的 Main class。以下是该结构的一些代码示例:
public abstract class A {
public static String testValue;
public static boolean valueSet() {
return testValue != null;
}
}
public class B extends A {
static {
System.out.println("TEST");
testValue = "foo";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(B.testValue);
System.out.println(B.valueSet());
System.out.println(new B());
System.out.println(B.testValue);
System.out.println(B.valueSet());
}
}
我希望得到以下输出:
foo
true
foo
true
但是,代码输出的是:
null
false
foo
true
我的最终目标是在每个subclass中将testValue
设置为某个值,并在superclass中只实现一次检查功能。它必须是静态的,因为它应该只检查字符串与 A
类型的对象的兼容性。将使用方法定义为 public static abstract
是不可能的,因为我已经 read,并且无法抽象值,所以我也不能使用它。我希望代码尽可能简单,而不是为每个 subclass.
重新实现检查
感谢您的帮助或提示!
您没有在调用 new B()
之前初始化 class B
(在您的代码示例中)!
首先,您有点误用 Java 通过子类型访问静态变量的可能性。没有B.testValue
,只有A.testValue
。编译器实际上取代了它。对B.valueSet()
的调用也是如此。只有 A.valueSet()
.
所以,你写
System.out.println(B.testValue);
System.out.println(B.valueSet());
但编译器将其替换为
System.out.println(A.testValue);
System.out.println(A.valueSet());
因为静态成员确实属于声明它们的 class。
对您的代码稍作改动表明:
public class B extends A {
public static String foo = "foo"; // Note the new static variable here.
static {
System.out.println("TEST");
testValue = "foo";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(B.foo); // Note the new access here.
System.out.println(B.testValue);
System.out.println(B.valueSet());
System.out.println(new B());
System.out.println(B.testValue);
System.out.println(B.valueSet());
}
}
现在可以正确打印
TEST
foo
foo
true
B@2a139a55
foo
true
因为现在你的 class B
首先被初始化了。
提示:访问静态成员时应始终使用声明 class 作为引用。
正如问题下方的评论所暗示的那样,这个问题没有任何问题;但是,您的代码无法复制,因为它会绝不会,打印您所说的任何内容。
一般来说,使用调试器并逐步查看执行流程总是一个好主意。
让我们看看发生了什么:
System.out.println(B.testValue);
与 class A
交互,因为 B
没有静态 testValue
成员,但 A
有(是的,静态成员是可访问的在层次结构链中,只要它们不被另一个静态成员隐藏,定义为 child class);因此 null
被打印出来,作为引用类型的默认值,是 null
;
- 同样,您的
B.testValue()
returns false
,因为 testValue != null
在 class A
; 中是错误的
- 通过执行
System.out.println(new B());
,当您与 class B
交互时,您将在 foo
和 true
之前打印额外的两行(您在问题中省略)第一次定义并将它加载到 JVM 中 - 因此,它的静态块被执行(TEST
被打印并且 testValue
(superclass 的)被设置为 "foo"
);
- 然后,你又是
System.out.println(B.testValue);
,这次这个字段已经用"foo"
初始化了,所以打印后者;
- 并且
B.valueSet()
将分别打印 true
.
也就是:
null
false
TEST
Object Reference, like B@2133c8f8
foo
true
今天我 运行 关注以下问题:
我有三个 classes,(superclass) A,(subclass) B 和我的 Main class。以下是该结构的一些代码示例:
public abstract class A {
public static String testValue;
public static boolean valueSet() {
return testValue != null;
}
}
public class B extends A {
static {
System.out.println("TEST");
testValue = "foo";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(B.testValue);
System.out.println(B.valueSet());
System.out.println(new B());
System.out.println(B.testValue);
System.out.println(B.valueSet());
}
}
我希望得到以下输出:
foo
true
foo
true
但是,代码输出的是:
null
false
foo
true
我的最终目标是在每个subclass中将testValue
设置为某个值,并在superclass中只实现一次检查功能。它必须是静态的,因为它应该只检查字符串与 A
类型的对象的兼容性。将使用方法定义为 public static abstract
是不可能的,因为我已经 read,并且无法抽象值,所以我也不能使用它。我希望代码尽可能简单,而不是为每个 subclass.
感谢您的帮助或提示!
您没有在调用 new B()
之前初始化 class B
(在您的代码示例中)!
首先,您有点误用 Java 通过子类型访问静态变量的可能性。没有B.testValue
,只有A.testValue
。编译器实际上取代了它。对B.valueSet()
的调用也是如此。只有 A.valueSet()
.
所以,你写
System.out.println(B.testValue);
System.out.println(B.valueSet());
但编译器将其替换为
System.out.println(A.testValue);
System.out.println(A.valueSet());
因为静态成员确实属于声明它们的 class。
对您的代码稍作改动表明:
public class B extends A {
public static String foo = "foo"; // Note the new static variable here.
static {
System.out.println("TEST");
testValue = "foo";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(B.foo); // Note the new access here.
System.out.println(B.testValue);
System.out.println(B.valueSet());
System.out.println(new B());
System.out.println(B.testValue);
System.out.println(B.valueSet());
}
}
现在可以正确打印
TEST
foo
foo
true
B@2a139a55
foo
true
因为现在你的 class B
首先被初始化了。
提示:访问静态成员时应始终使用声明 class 作为引用。
正如问题下方的评论所暗示的那样,这个问题没有任何问题;但是,您的代码无法复制,因为它会绝不会,打印您所说的任何内容。
一般来说,使用调试器并逐步查看执行流程总是一个好主意。
让我们看看发生了什么:
System.out.println(B.testValue);
与class A
交互,因为B
没有静态testValue
成员,但A
有(是的,静态成员是可访问的在层次结构链中,只要它们不被另一个静态成员隐藏,定义为 child class);因此null
被打印出来,作为引用类型的默认值,是null
;- 同样,您的
B.testValue()
returnsfalse
,因为testValue != null
在class A
; 中是错误的
- 通过执行
System.out.println(new B());
,当您与class B
交互时,您将在foo
和true
之前打印额外的两行(您在问题中省略)第一次定义并将它加载到 JVM 中 - 因此,它的静态块被执行(TEST
被打印并且testValue
(superclass 的)被设置为"foo"
); - 然后,你又是
System.out.println(B.testValue);
,这次这个字段已经用"foo"
初始化了,所以打印后者; - 并且
B.valueSet()
将分别打印true
.
也就是:
null
false
TEST
Object Reference, like B@2133c8f8
foo
true