tom*_*ekK 6 java static-variables nullpointerexception
我只是非常奇怪(对我而言)java的行为.我有以下课程:
public abstract class Unit {
public static final Unit KM = KMUnit.INSTANCE;
public static final Unit METERS = MeterUnit.INSTANCE;
protected Unit() {
}
public abstract double getValueInUnit(double value, Unit unit);
protected abstract double getValueInMeters(double value);
}
Run Code Online (Sandbox Code Playgroud)
和:
public class KMUnit extends Unit {
public static final Unit INSTANCE = new KMUnit();
private KMUnit() {
}
//here are abstract methods overriden
}
public class MeterUnit extends Unit {
public static final Unit INSTANCE = new MeterUnit();
private MeterUnit() {
}
///abstract methods overriden
}
Run Code Online (Sandbox Code Playgroud)
我的测试用例:
public class TestMetricUnits extends TestCase {
@Test
public void testConversion() {
System.out.println("Unit.METERS: " + Unit.METERS);
System.out.println("Unit.KM: " + Unit.KM);
double meters = Unit.KM.getValueInUnit(102.11, Unit.METERS);
assertEquals(0.10211, meters, 0.00001);
}
}
Run Code Online (Sandbox Code Playgroud)
我希望如此:
但是当我用maven在控制台中运行我的测试用例时,我的结果是:
T E S T S
Running de.audi.echargingstations.tests.TestMetricUnits<br/>
Unit.METERS: m<br/>
Unit.KM: null<br/>
Tests run: 3, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.089 sec <<< FAILURE! - in de.audi.echargingstations.tests.TestMetricUnits<br/>
testConversion(de.audi.echargingstations.tests.TestMetricUnits) Time elapsed: 0.011 sec <<< ERROR!<br/>
java.lang.NullPointerException: null<br/>
at <br/>de.audi.echargingstations.tests.TestMetricUnits.testConversion(TestMetricUnits.java:29)
<br/>
Results :
Tests in error:
TestMetricUnits.testConversion:29 NullPointer
Run Code Online (Sandbox Code Playgroud)
有趣的是,当我从eclipse通过JUnit运行这个测试时,一切都很好,我没有NullPointerException
,在控制台中我有:
Unit.METERS: m
Unit.KM: km
Run Code Online (Sandbox Code Playgroud)
所以问题是:单位中的KM变量为空的原因是什么(同时METERS不为空)
静态初始化可能很棘手。您在A-> B和B-> A之间具有相互依赖关系。之所以这样做是个坏主意,是因为JVM如何从一个类的顶部开始从上至下加载静态数据-如果它遇到了一个尚未初始化的新类, ,它将一直等到它初始化该类及其依赖项为止,直到一切准备就绪,然后继续进行。
除非已经加载了一个类。如果A指代B,而B指代A,则它无法第二次开始加载A,否则将成为无限循环(因为A会再次加载B,从而加载A)。因此,在这种情况下,它基本上表示“已经开始加载该文件,无需执行其他操作,而是继续进行”。
故事的寓意:根据加载类的顺序,单击此行时可能不会初始化KMUnit.INSTANCE:
public static final Unit KM = KMUnit.INSTANCE;
假设您是JVM,然后开始加载KMUnit。它必须在第一次看到它时就加载Unit,以便例如在初次创建时(或者也许在之前,创建一个是Unit的子类的对象)-我对JVM静态加载感到迷惑)。但这又会触发Unit中的静态初始化,包括以下内容:
public static final Unit KM = KMUnit.INSTANCE;
public static final Unit METERS = MeterUnit.INSTANCE;
Run Code Online (Sandbox Code Playgroud)
好。现在已经完成了Unit的加载,并且我们完成了为KMUnit.INSTANCE构造KMUnit的操作……但是,等待-我们已经设置了KM = KMUnit.INSTANCE
,当时它为null。因此它保持为空。哎呀。
另一方面,如果首先加载Unit,那么它将在初始化之前等待KMUnit加载,因此在实际运行初始化程序时会设置KMUnit.INSTANCE。
我认为。我有点睡眠不足,而且我不是类加载方面的专家。
归档时间: |
|
查看次数: |
5577 次 |
最近记录: |