問題の説明
コード例1
まず、エラーを報告するコードを投稿します。
@Test
public void test21() {
Spaces spaces = new Spaces();
// 正常构建对象spaces
spaces.setCommodityName("CommodityName");
spaces.setCommodityPrice("CommodityPrice");
spaces.setCommodityType("CommodityType");
// 此时注意spaces.getAge为空
if (spaces != null && 1 == spaces.getAge()) {
System.out.println(1);
}
// 结果:
// java.lang.NullPointerException
// at someverynbtest.Eighty.test21(Eighty.java:396)
// at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
// at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
// at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
// at java.lang.reflect.Method.invoke(Method.java:498)
// at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
// at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
// at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
// at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
// at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
// at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
// at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
// at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
// at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
// at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
// at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
// at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
// at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
// at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
// at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
// at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
// at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
// at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
// at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
// at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
}
class Spaces {
private String commodityName;
private String commodityPrice;
private String commodityType;
private Integer age;
public String getCommodityName() {
return commodityName;
}
public void setCommodityName(String commodityName) {
this.commodityName = commodityName;
}
public String getCommodityPrice() {
return commodityPrice;
}
public void setCommodityPrice(String commodityPrice) {
this.commodityPrice = commodityPrice;
}
public String getCommodityType() {
return commodityType;
}
public void setCommodityType(String commodityType) {
this.commodityType = commodityType;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
説明
Spacesオブジェクト内の3つのプロパティ
private String commodityName;
private String commodityPrice;
private String commodityType;
すべて正常に入力されますが、整数型の年齢は入力されません。つまり、nullです。
test21テストメソッドを実行すると、nullポインターが報告されます。プロンプトによると、この行にあることがわかります。
if (spaces != null && 1 == spaces.getAge()) {
System.out.println(1);
}
つまり、1 == space.getAge()、この書き方に何か問題があります。整数1とnullを等式比較に使用することはできませんか?
コード例2
2番目の例を見てください。
@Test
public void test22() {
Spaces2 spaces = new Spaces2();
// 正常构建对象spaces
spaces.setCommodityName("CommodityName");
spaces.setCommodityPrice("CommodityPrice");
spaces.setCommodityType("CommodityType");
// 此时注意spaces.getAge为空
if (spaces != null && 1 == spaces.getAge()) {
System.out.println(1);
}
// 结果:(无内容)
// 代表正常,并没有报出空指针
}
class Spaces2 {
private String commodityName;
private String commodityPrice;
private String commodityType;
private int age;
public String getCommodityName() {
return commodityName;
}
public void setCommodityName(String commodityName) {
this.commodityName = commodityName;
}
public String getCommodityPrice() {
return commodityPrice;
}
public void setCommodityPrice(String commodityPrice) {
this.commodityPrice = commodityPrice;
}
public String getCommodityType() {
return commodityType;
}
public void setCommodityType(String commodityType) {
this.commodityType = commodityType;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
コード例2と例1の最大の違いは、整数型のエージがint型に置き換えられていることです。現時点では、同じテストコードでエラーが報告されることはありません。
結論を導き出すことができます:
int型はnullと比較できます(nullポインターは報告されません)が、integer型はできません(nullポインターが報告されます)
では、ラッパークラススペースの年齢フィールドで整数型を使用する必要がある場合はどうなるでしょうか。
解決する
コード例3
@Test
public void test23() {
Spaces spaces = new Spaces();
// 正常构建对象spaces
spaces.setCommodityName("CommodityName");
spaces.setCommodityPrice("CommodityPrice");
spaces.setCommodityType("CommodityType");
// 此时注意spaces.getAge为空
if (spaces != null && spaces.getAge() != null && 1 == spaces.getAge()) {
System.out.println(1);
}
// 结果:(无内容)
// 代表正常,并没有报出空指针
}
ここで使用されているスペースは整数型バージョンであり、nullポインターは報告されないため、実際には、年齢値を判断する前にnull操作を追加するだけです。
spaces != null && spaces.getAge() != null && 1 == spaces.getAge()
結論は
nullであることがわかっていない整数型の値を判断する場合(デフォルトでは、整数型のメンバーは別のpoクラスにあると見なされます)、次の3つの条件が並行して必要です
。
spaces != null && spaces.getAge() != null && 1 == spaces.getAge()
nullであることがわかっていないint型の値を判断する場合(デフォルトでは、int型のメンバーは別のpoクラスにあると見なされます)、並行して必要な条件は2つだけです。
例:
spaces != null && 1 == spaces.getAge()