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เมื่อเป็นinull
*ตั้งแต่ 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;
}