Integer i = ...
switch (i){
case null:
doSomething0();
break;
}
ในรหัสข้างต้นฉันไม่สามารถใช้ null ในงบกรณีสวิตช์ ฉันจะทำสิ่งนี้ต่างออกไปได้อย่างไร ฉันไม่สามารถใช้default
เพราะแล้วฉันต้องการทำอย่างอื่น
Integer i = ...
switch (i){
case null:
doSomething0();
break;
}
ในรหัสข้างต้นฉันไม่สามารถใช้ null ในงบกรณีสวิตช์ ฉันจะทำสิ่งนี้ต่างออกไปได้อย่างไร ฉันไม่สามารถใช้default
เพราะแล้วฉันต้องการทำอย่างอื่น
คำตอบ:
ไม่สามารถใช้switch
คำสั่งใน Java ได้ ตรวจสอบnull
ก่อนswitch
:
if (i == null) {
doSomething0();
} else {
switch (i) {
case 1:
// ...
break;
}
}
คุณไม่สามารถใช้วัตถุพลการในswitch
งบ* เหตุผลที่คอมไพเลอร์ไม่ได้บ่นเกี่ยวกับการswitch (i)
ที่i
เป็นInteger
เป็นเพราะ Java อัตโนมัติ unboxes ไปยังInteger
int
ในฐานะที่เป็น assylias แล้วกล่าวว่า unboxing จะโยนNullPointerException
เมื่อเป็นi
null
*ตั้งแต่ Java 7 คุณสามารถใช้String
ในswitch
ข้อความสั่ง
ข้อมูลเพิ่มเติมเกี่ยวกับswitch
(รวมถึงตัวอย่างที่มีตัวแปร null) ในOracle Docs - Switch
null
ไม่สามารถเป็นกรณีที่ถูกต้องเมื่อทำงานกับString
และenum
ประเภท บางทีenum
การนำไปปฏิบัตินั้นอาศัยการโทรหาordinal()
เบื้องหลัง (แม้ว่าจะเป็นเช่นนั้นทำไมไม่ถือว่าnull
เป็น 'อันดับ' ของ -1?) และString
รุ่นนี้ใช้บางสิ่งบางอย่างโดยใช้intern()
และการเปรียบเทียบตัวชี้ (หรืออาศัยบางสิ่งบางอย่าง วัตถุ)?
switch ((i != null) ? i : DEFAULT_VALUE) {
//...
}
switch(i)
จะโยน NullPointerException ถ้าฉันเป็นnull
เพราะมันจะพยายามที่จะ unbox เป็นInteger
int
ดังนั้นcase null
สิ่งที่ผิดกฎหมายก็จะไม่เกิดขึ้น
คุณต้องตรวจสอบว่าฉันไม่ได้เป็นโมฆะก่อนswitch
คำสั่ง
เอกสาร Java ระบุไว้อย่างชัดเจนว่า:
ข้อห้ามในการใช้ null เป็นฉลากสวิตช์ป้องกันหนึ่งจากการเขียนรหัสที่ไม่สามารถดำเนินการได้ หากการแสดงออกของสวิทช์เป็นประเภทอ้างอิงเช่นชนิดดั้งเดิมแบบกล่องหรือ enum ข้อผิดพลาดรันไทม์จะเกิดขึ้นหากการแสดงออกประเมินเป็นโมฆะในเวลาทำงาน
คุณจะต้องตรวจสอบความถูกต้องของโมฆะก่อนที่จะดำเนินการคำสั่ง Swithch
if (i == null)
case null: // will never be executed, therefore disallowed.
ได้รับ:
public enum PersonType {
COOL_GUY(1),
JERK(2);
private final int typeId;
private PersonType(int typeId) {
this.typeId = typeId;
}
public final int getTypeId() {
return typeId;
}
public static PersonType findByTypeId(int typeId) {
for (PersonType type : values()) {
if (type.typeId == typeId) {
return type;
}
}
return null;
}
}
สำหรับฉันแล้วโดยทั่วไปจะจัดแนวกับตารางค้นหาในฐานข้อมูล (สำหรับตารางที่ไม่ค่อยมีการปรับปรุงเท่านั้น)
อย่างไรก็ตามเมื่อฉันพยายามที่จะใช้findByTypeId
ในคำสั่งเปลี่ยน (จากส่วนใหญ่ผู้ใช้ใส่) ...
int userInput = 3;
PersonType personType = PersonType.findByTypeId(userInput);
switch(personType) {
case COOL_GUY:
// Do things only a cool guy would do.
break;
case JERK:
// Push back. Don't enable him.
break;
default:
// I don't know or care what to do with this mess.
}
... เป็นคนอื่นได้รับรู้ผลการนี้ในการ NPE switch(personType) {
@ หนึ่งในการแก้ไข (เช่น "วิธีแก้ปัญหา") ที่ฉันเริ่มใช้คือการเพิ่มUNKNOWN(-1)
ประเภท
public enum PersonType {
UNKNOWN(-1),
COOL_GUY(1),
JERK(2);
...
public static PersonType findByTypeId(int id) {
...
return UNKNOWN;
}
}
ตอนนี้คุณไม่จำเป็นต้องตรวจสอบค่าว่างในตำแหน่งใดและคุณสามารถเลือกหรือไม่จัดการUNKNOWN
ประเภทได้ (หมายเหตุ: -1
เป็นตัวบ่งชี้ที่ไม่น่าเป็นไปได้ในสถานการณ์ทางธุรกิจ แต่เลือกสิ่งที่เหมาะสมกับการใช้งานของคุณ)
UNKNOWN
เป็นทางออกที่ดีที่สุดในเรื่องนี้ฉันเคยเห็นและเอาชนะ nullchecks
คุณต้องทำ
if (i == null) {
doSomething0();
} else {
switch (i) {
}
}
บางไลบรารีพยายามเสนอทางเลือกให้กับswitch
คำสั่งbuiltin java Vavrเป็นหนึ่งในนั้นพวกเขาพูดคุยกับมันเพื่อจับคู่รูปแบบ
นี่คือตัวอย่างจากเอกสารประกอบ :
String s = Match(i).of(
Case($(1), "one"),
Case($(2), "two"),
Case($(), "?")
);
คุณสามารถใช้เพรดิเคตใด ๆ แต่พวกเขาเสนอให้พวกเขาหลายคนออกจากกล่องและ$(null)
ถูกต้องตามกฎหมายอย่างสมบูรณ์ ฉันพบว่านี่เป็นทางออกที่หรูหรากว่าทางเลือกอื่น แต่ต้องใช้ java8 และการพึ่งพา vavr ไลบรารี่ ...
คุณยังสามารถใช้String.valueOf((Object) nullableString)
เช่น
switch (String.valueOf((Object) nullableString)) {
case "someCase"
//...
break;
...
case "null": // or default:
//...
break;
}
ดู SO Q / A ที่น่าสนใจ: ทำไม String.valueOf (null) จึงโยน NullPointerException
switch (String.valueOf(value)){
case "null":
default:
}
คุณทำไม่ได้ คุณสามารถใช้แบบดั้งเดิม (int, char, short, byte) และ String (Strings ใน java 7 เท่านั้น) ในสวิตช์ primitives ต้องไม่เป็นค่าว่าง
ตรวจสอบi
ในสภาพที่แยกต่างหากก่อนที่จะเปลี่ยน
เพียงแค่พิจารณาว่าสวิตช์อาจทำงานได้อย่างไร
ตามคำตอบ @tetsuo ด้วย java 8:
Integer i = ...
switch (Optional.ofNullable(i).orElse(DEFAULT_VALUE)) {
case DEFAULT_VALUE:
doDefault();
break;
}