Java 中的静态初始化?
Static Initialization in Java?
我正在尝试执行以下代码:
public class StaticTest {
private static List<String> dat1;
{
dat1 = new ArrayList<>();
}
private StaticTest(){
System.out.println(dat1.contains("a")); //Marked Line 2: this one is not throwing
}
public static void main(String[] args) {
System.out.println(dat1.contains("a")); //Marked Line 1: This line throws null pointer
new StaticTest();
}
}
我试图执行上面的代码,我在标记行 1 得到了 Null pointer exception
。但是当我评论标记行 1 时,我得到了输出。
为什么我在第一种情况下得到异常,而在第二种情况下却没有?
当我使用private static List<String> dat1= new ArrayList<>();
时,没有抛出异常。
简单:
System.out.println(dat1.contains("a"));
运行是一个构造器(因为它在构造器内部!)。
运行构造函数的一部分是:运行 class.
的所有非静态初始化程序块
鉴于:
public static void main(String[] args) {
System.out.println(dat1.contains("a")); //Marked Line 1: This line
只 运行 你的 static 初始值设定项 - 但 没有 构造函数代码(它确实 - 但 在那一行之后)。
所以你的问题是这个初始化块:
{
dat1 = new ArrayList<>();
}
不是静态的!
换句话说:您的问题是由 static/non-static 以非常不健康的方式混合引起的。如果字段是 static,请确保 static 初始化代码将初始化它。
顺便说一句:合理的解决方案是简单地做:
private final static List<String> data = new ArrayList<>();
这样可以确保尽快初始化列表;然后编译器甚至会在您忘记初始化它时告诉您。
这段代码
{
dat1 = new ArrayList<>();
}
这个构造函数块。这将在 super() 之后的每个构造函数中执行,因此它不会 运行 在 Mark1 上。
如果您有这样的代码,它将在 class 加载时执行。
static {
dat1 = new ArrayList<>();
}
这里有更多细节
http://www.jusfortechies.com/java/core-java/static-blocks.php
您的代码:
{
dat1 = new ArrayList<>();
}
是一个非静态初始化器。当您使用 new StaticTest()
调用构造函数时,将调用它。之后dat1
会被初始化。
您可以通过在代码前面添加 static
关键字来将您的代码更改为静态初始化:
static
{
dat1 = new ArrayList<>();
}
那么这两种情况都适用。
嗨@kajal 请参考下面的正确代码:-
public class StaticTest {
private static List<String> dat1;
static
{
dat1 = new ArrayList<String>();
}
private StaticTest(){
System.out.println(dat1.contains("a")); //Marked Line 2: this one is not throwing
}
public static void main(String[] args) {
System.out.println(dat1.contains("a")); //Marked Line 1: This line throws null pointer
new StaticTest();
}
}
实例块在您创建该 class 的实例时执行。
问你为什么得到 NullPointerException
:-
请找到下面的 StaticTest
class 执行流程:-
- 首先,所有导入 class 将像这样加载:-
Object
class 2.java.lang
包 Class 3.java.util.ArrayList
Class.
- 编译器通过 StaticTest Class 并为您的情况下的所有静态成员分配内存
dat1
.
- 现在 javac 编译器搜索用于执行的静态块。在你的情况下,它们不是静态块。
- 现在编译器执行
main
方法并执行 System.out.println(dat1.contains("a"));
被调用为 null.contains("a");
这表明执行但正如我所说Instance 块在您创建该 class 的实例时执行。所以 dat1
在你创建对象 new StaticTest();
时被初始化
我正在尝试执行以下代码:
public class StaticTest {
private static List<String> dat1;
{
dat1 = new ArrayList<>();
}
private StaticTest(){
System.out.println(dat1.contains("a")); //Marked Line 2: this one is not throwing
}
public static void main(String[] args) {
System.out.println(dat1.contains("a")); //Marked Line 1: This line throws null pointer
new StaticTest();
}
}
我试图执行上面的代码,我在标记行 1 得到了 Null pointer exception
。但是当我评论标记行 1 时,我得到了输出。
为什么我在第一种情况下得到异常,而在第二种情况下却没有?
当我使用private static List<String> dat1= new ArrayList<>();
时,没有抛出异常。
简单:
System.out.println(dat1.contains("a"));
运行是一个构造器(因为它在构造器内部!)。 运行构造函数的一部分是:运行 class.
的所有非静态初始化程序块鉴于:
public static void main(String[] args) {
System.out.println(dat1.contains("a")); //Marked Line 1: This line
只 运行 你的 static 初始值设定项 - 但 没有 构造函数代码(它确实 - 但 在那一行之后)。
所以你的问题是这个初始化块:
{
dat1 = new ArrayList<>();
}
不是静态的!
换句话说:您的问题是由 static/non-static 以非常不健康的方式混合引起的。如果字段是 static,请确保 static 初始化代码将初始化它。
顺便说一句:合理的解决方案是简单地做:
private final static List<String> data = new ArrayList<>();
这样可以确保尽快初始化列表;然后编译器甚至会在您忘记初始化它时告诉您。
这段代码
{
dat1 = new ArrayList<>();
}
这个构造函数块。这将在 super() 之后的每个构造函数中执行,因此它不会 运行 在 Mark1 上。
如果您有这样的代码,它将在 class 加载时执行。
static {
dat1 = new ArrayList<>();
}
这里有更多细节 http://www.jusfortechies.com/java/core-java/static-blocks.php
您的代码:
{
dat1 = new ArrayList<>();
}
是一个非静态初始化器。当您使用 new StaticTest()
调用构造函数时,将调用它。之后dat1
会被初始化。
您可以通过在代码前面添加 static
关键字来将您的代码更改为静态初始化:
static
{
dat1 = new ArrayList<>();
}
那么这两种情况都适用。
嗨@kajal 请参考下面的正确代码:-
public class StaticTest {
private static List<String> dat1;
static
{
dat1 = new ArrayList<String>();
}
private StaticTest(){
System.out.println(dat1.contains("a")); //Marked Line 2: this one is not throwing
}
public static void main(String[] args) {
System.out.println(dat1.contains("a")); //Marked Line 1: This line throws null pointer
new StaticTest();
}
}
实例块在您创建该 class 的实例时执行。
问你为什么得到 NullPointerException
:-
请找到下面的 StaticTest
class 执行流程:-
- 首先,所有导入 class 将像这样加载:-
Object
class 2.java.lang
包 Class 3.java.util.ArrayList
Class.
- 编译器通过 StaticTest Class 并为您的情况下的所有静态成员分配内存
dat1
. - 现在 javac 编译器搜索用于执行的静态块。在你的情况下,它们不是静态块。
- 现在编译器执行
main
方法并执行System.out.println(dat1.contains("a"));
被调用为null.contains("a");
这表明执行但正如我所说Instance 块在您创建该 class 的实例时执行。所以dat1
在你创建对象new StaticTest();
时被初始化