ลองนึกภาพว่าคุณกำลังยืนอยู่ตรงทางแยกเหมือนฮีโร่จากภาพวาดชื่อดัง ถ้าคุณไปทางซ้าย คุณจะสูญเสียม้าของคุณ ถ้าคุณไปทางขวา คุณจะได้เรียนรู้ จะตั้งโปรแกรมสถานการณ์เช่นนี้ได้อย่างไร? คุณน่าจะรู้อยู่แล้วว่าเราตัดสินใจเช่นนั้นโดยใช้ โครงสร้าง if-thenและ if- then -else
แม้จะมีฟีเจอร์ใหม่ แต่วิธีการใช้ enum ก็มีความยืดหยุ่นมากกว่าและแนะนำให้ใช้: เราสามารถใช้ enum นี้ซ้ำได้หลายครั้ง
if (turn_left) {
System.out.println(«Коня потеряешь»);
}
if (turn_right) {
System.out.println(“Знания обретёшь”);
}
else
System.out.println(“Так и будешь стоять?”);
จะเกิดอะไรขึ้นถ้าไม่ใช่สองแทร็ก แต่มี 10 แทร็ก? มีทาง “ไปทางขวา” “ทางซ้ายอีกหน่อย” “ทางซ้ายอีกหน่อย” และอื่นๆ จำนวน 10 ชิ้น ? ลองนึกภาพว่าโค้ด if-then-elseของคุณจะเติบโตอย่างไรในเวอร์ชันนี้!
if (вариант1)
{… }
else if (вариант2)
{…}
…
else if (вариантN) ….
ดังนั้น คุณไม่มีเงื่อนไขทางแยกเพียงข้อเดียว แต่มีหลายเงื่อนไข เช่น 10 (สิ่งสำคัญที่นี่คือจำนวนส้อมมีจำกัด) สำหรับสถานการณ์ดังกล่าว จะมีตัวดำเนินการเลือกพิเศษ - switch case java
switch (ВыражениеДляВыбора) {
case (Значение1):
Код1;
break;
case (Значение2):
Код2;
break;
...
case (ЗначениеN):
КодN;
break;
default:
КодВыбораПоУмолчанию;
break;
}
ลำดับการดำเนินการในคำสั่งมีดังนี้:
- SelectionExpression ได้รับการประเมิน ถัดไป คำสั่ง switch จะเปรียบเทียบนิพจน์ผลลัพธ์กับค่าถัดไป (ตามลำดับที่แสดง)
- หาก SelectExpression ตรงกับค่า โค้ดที่อยู่หลังเครื่องหมายทวิภาคจะถูกดำเนินการ
- หาก พบโครงสร้าง ตัวแบ่งการควบคุมจะถูกถ่ายโอนไปนอกคำสั่งสวิตช์
- หากไม่พบรายการที่ตรงกันระหว่าง ExpressionForSelection และ Values การควบคุมจะถูกโอนไปยัง DefaultSelectionCode
-
ประเภท SelectionExpression สำหรับคำสั่งการเลือกสวิตช์ใน Java ต้องเป็นอย่างใดอย่างหนึ่งต่อไปนี้:
- ไบต์ , สั้น , ถ่าน , int _
- wrapper ของพวกเขาคือByte , Short , Character , Integer
- สตริง (ตั้งแต่ Java 7)
- การแจงนับ ( อีนัม ).
- บล็อกเริ่มต้นเป็นทางเลือก ดังนั้นหาก SelectionExpression และ Values ไม่ตรงกัน จะไม่มีการดำเนินการใด ๆ
- แบ่งเป็นทางเลือก หากไม่มีอยู่โค้ดจะดำเนินการต่อไป (โดยไม่สนใจการเปรียบเทียบค่าเพิ่มเติมในบล็อกกรณี) จนกว่า
break
จะพบคำสั่งสวิตช์แรกหรือจนกว่าจะสิ้นสุด - หากจำเป็นต้องรันโค้ดเดียวกันสำหรับตัวเลือกการเลือกหลายตัว เพื่อหลีกเลี่ยงการทำซ้ำเราจะระบุค่าที่สอดคล้องกันหลายค่าที่ด้านหน้าใน บล็อก ตัวพิมพ์ ที่ต่อเนื่อง กัน
มาดูการฝึกใช้คำสั่ง switch ใน Java กันดีกว่า
ไม่ต้องกังวล เราจบทฤษฎีนี้แล้ว และหลังจากตัวอย่างเพิ่มเติม ทุกอย่างจะชัดเจนขึ้นมาก มาเริ่มกันเลย เรามาดูตัวอย่างจากดาราศาสตร์เกี่ยวกับดาวเคราะห์ในระบบสุริยะกัน ตามกฎระเบียบระหว่างประเทศล่าสุด เราจะไม่รวมดาวพลูโต (เนื่องจากคุณสมบัติของวงโคจรของมัน) ให้เราจำไว้ว่าดาวเคราะห์ของเราอยู่ห่างจากดวงอาทิตย์ตามลำดับต่อไปนี้: ดาวพุธ ดาวศุกร์ โลก ดาวอังคาร ดาวพฤหัสบดี ดาวเสาร์ ดาวยูเรนัส และดาวเนปจูน มาสร้างวิธีการ Java ที่ได้รับอินพุตหมายเลขซีเรียลของดาวเคราะห์ (สัมพันธ์กับระยะห่างจากดวงอาทิตย์) และเอาต์พุตจะสร้างองค์ประกอบหลักของบรรยากาศของดาวเคราะห์ดวงนี้ในรูปแบบของList <String> ฉันขอเตือนคุณว่าดาวเคราะห์บางดวงมีองค์ประกอบบรรยากาศคล้ายกัน ดังนั้น ดาวศุกร์และดาวอังคารจึงมีคาร์บอนไดออกไซด์เป็นส่วนใหญ่ ดาวพฤหัสบดีและดาวเสาร์ประกอบด้วยไฮโดรเจนและฮีเลียม และดาวยูเรนัสและดาวเนปจูน นอกเหนือจากก๊าซคู่สุดท้ายแล้ว ยังมีมีเทนอีกด้วย ฟังก์ชั่นของเรา:public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
List<String> result = new ArrayList<>();
switch (seqNumberFromSun) {
case 1: result.add("No Atmosphere");
break;
case 2:
case 4: result.add("Carbon dioxide");
break;
case 3: result.add("Carbon dioxide");
result.add("Nitrogen");
result.add("Oxygen");
break;
case 5:
case 6: result.add("Hydrogen");
result.add("Helium");
break;
case 7:
case 8: result.add("Methane");
result.add("Hydrogen");
result.add("Helium");
break;
default:
break;
}
return result;
}
โปรดทราบ: เราเปรียบเทียบรหัสเดียวกันกับดาวเคราะห์ที่มีองค์ประกอบบรรยากาศเหมือนกัน และเราทำสิ่งนี้โดยใช้โครงสร้างเคส ที่ต่อเนื่องกัน ดังนั้นหากเราต้องการได้องค์ประกอบบรรยากาศของดาวเคราะห์บ้านเกิดของเรา เราก็เรียกวิธีการของเราว่าพารามิเตอร์ 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
การทดลองกับตัวแบ่ง จะเกิดอะไรขึ้นถ้าเราลบ คำสั่ง แบ่ง ทั้งหมดออก ? เรามาลองในทางปฏิบัติกัน:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
List<String> result = new ArrayList<>();
switch (seqNumberFromSun) {
case 1: result.add("No Atmosphere");
case 2:
case 4: result.add("Carbon dioxide");
case 3: result.add("Carbon dioxide");
result.add("Nitrogen");
result.add("Oxygen");
case 5:
case 6: result.add("Hydrogen");
result.add("Helium");
case 7:
case 8: result.add("Methane");
result.add("Hydrogen");
result.add("Helium");
default:
}
return result;
}
หากเราพิมพ์ผลลัพธ์ของวิธีนี้System.out.println(getPlanetAtmosphere(3))
ดาวเคราะห์บ้านเกิดของเราจะไม่เหมาะกับสิ่งมีชีวิตมากนัก หรือเหมาะ? ตัดสินด้วยตัวคุณเอง: [คาร์บอนไดออกไซด์ ไนโตรเจน ออกซิเจน ไฮโดรเจน ฮีเลียม มีเทน ไฮโดรเจน ฮีเลียม] ทำไมสิ่งนี้จึงเกิดขึ้น โปรแกรมดำเนินการทุกกรณีหลังจากแมตช์แรกและจนกระทั่งสิ้นสุดบล็อกสวิตช์
การหยุดเพิ่มประสิทธิภาพมากเกินไป
โปรดทราบว่าเราสามารถปรับปรุงวิธีการได้ด้วยการจัดเรียง คำสั่ง แบ่งและตัวเลือกการเลือก ที่แตกต่างกันpublic static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
List<String> result = new ArrayList<>();
switch (seqNumberFromSun) {
case 1: result.add("No Atmosphere");
break;
case 3: result.add("Nitrogen");
result.add("Oxygen");
case 2:
case 4: result.add("Carbon dioxide");
break;
case 7:
case 8: result.add("Methane");
case 5:
case 6: result.add("Hydrogen");
result.add("Helium");
}
return result;
}
ดูสั้นลงใช่ไหมล่ะ? เราลดจำนวนคำสั่งทั้งหมดลงโดยการเล่นกับ ลำดับเคสและการจัดกลุ่มใหม่ ตอนนี้ก๊าซแต่ละประเภทจะถูกเพิ่มเข้าไปในรายการด้วยรหัสเพียงบรรทัดเดียวเท่านั้น รายการตัวอย่างสุดท้ายของวิธีนี้จะแสดงขึ้นเพื่อสาธิตการทำงานเท่านั้นไม่แนะนำอย่างยิ่งให้เขียนในลักษณะดังกล่าว หากผู้เขียน (และโปรแกรมเมอร์บุคคลที่สามมากกว่านั้น) ของโค้ดที่คล้ายกันต้องดูแลรักษามันไว้ การคืนค่าตรรกะสำหรับการสร้างบล็อกการเลือกและโค้ดที่ปฏิบัติการได้สำหรับคำสั่ง java switch จะเป็นเรื่องยากมาก
ความแตกต่างจากถ้า
แม้ว่าคำสั่ง ifและswitchจะมีลักษณะคล้ายกัน แต่อย่าลืมว่าสวิตช์ตัวดำเนินการแบบเลือกหลายตัวเลือกจะยึดตัวเลือกการดำเนินการตาม SPECIFIC VALUE ในขณะที่ if อาจเป็นนิพจน์เชิงตรรกะใดก็ได้ คำนึงถึงข้อเท็จจริงนี้เมื่อออกแบบโค้ดของคุณ มาดูนวัตกรรมต่างๆ ของสวิตช์ใน Java เวอร์ชันต่างๆ กันดีกว่าสลับใน Java 7
ก่อนที่ Java 7 จะสามารถใช้ไบต์, short, char และ int primitives เป็นค่าสำหรับสวิตช์ได้ นอกจากนี้ยังมีการรองรับ enum และ wrapper ประเภทดั้งเดิมที่แสดงไว้ด้านบน: อักขระ ไบต์ แบบสั้น และจำนวนเต็ม แต่บ่อยครั้งเราจำเป็นต้องค้นหาค่าของสตริงสวิตช์ Java! นี่คือสิ่งที่จะดูเหมือนใน Java 6:DayOfWeek day = DayOfWeek.fromValue("Thursday");
switch (day) {
case MONDAY:
System.out.println("Today is windy !");
break;
case THURSDAY:
System.out.println("Today is sunny !");
break;
case WEDNESDAY:
System.out.println("Today is rainy!");
break;
default:
System.out.println("Oooops, something wrong !");
และแจงนับ:
public enum DayOfWeek {
MONDAY("Monday"),
THURSDAY("Thursday"),
WEDNESDAY("Wednesday"),
NOT_FOUND("Not found");
private final String value;
DayOfWeek(final String value) {
this.value = value;
}
public static DayOfWeek fromValue(String value) {
for (final DayOfWeek dayOfWeek : values()) {
if (dayOfWeek.value.equalsIgnoreCase(value)) {
return dayOfWeek;
}
}
return NOT_FOUND;
}
}
แต่เริ่มต้นด้วย Java 7 มันเป็นไปได้ที่จะใช้ประเภท String เป็นค่าสำหรับสวิตช์:
String day = "Thursday";
switch (day) {
case "Monday":
System.out.println("Today is windy !");
break;
case "Thursday":
System.out.println("Today is sunny !");
break;
case "Wednesday":
System.out.println("Today is rainy!");
break;
default:
System.out.println("Oooops, something wrong !");
}
สลับใน Java 12
Java 12 ได้ปรับปรุงนิพจน์สวิตช์สำหรับการจับคู่รูปแบบ หากเราใช้ Switch ดังตัวอย่างด้านบน เพื่อตั้งค่าของตัวแปรบางตัว เราต้องคำนวณค่าและกำหนดให้กับตัวแปรที่กำหนด จากนั้นจึงใช้ตัวแบ่ง:int count = 2;
int value;
switch (count) {
case 1:
value = 12;
break;
case 2:
value = 32;
break;
case 3:
value = 52;
break;
default:
value = 0;
}
แต่ด้วยความสามารถของ Java 12 เราจึงสามารถเขียนนิพจน์นี้ใหม่ได้ดังนี้:
int value = switch (count) {
case 1:
break 12;
case 2:
break 32;
case 3:
break 52;
default:
break 0;
};
มาดูการเปลี่ยนแปลงกันสักหน่อย:
-
หากก่อนหน้านี้เราตั้งค่าตัวแปรไว้ภายใน case block เนื่องจากคำสั่ง switch เองไม่สามารถส่งคืนสิ่งใดได้ ตอนนี้เรามีโอกาสดังกล่าว และเราส่งคืนค่าโดยตรงโดยใช้ switch
-
ก่อนหน้านี้เราไม่สามารถมีสิ่งใดที่อยู่ทางขวาของตัวแบ่งอีกต่อไป แต่ตอนนี้เราใช้มันเป็นคำสั่ง return เพื่อส่งคืนค่าของสวิตช์ของเรา เครื่องหมายโคลอนทำเครื่องหมายจุดเริ่มต้นในบล็อกคำสั่ง นั่นคือจากจุดนั้น การดำเนินการของโค้ดทั้งหมดด้านล่างจะเริ่มต้นขึ้น แม้ว่าจะพบป้ายกำกับอื่นก็ตาม
ผลลัพธ์ที่ได้คือการเปลี่ยนผ่านจากจุดหนึ่งไปอีกจุดหนึ่ง ซึ่งเรียกอีกอย่างว่าการล้มผ่าน
int count = 2;
int value = switch (count) {
case 1 -> 12;
case 2 -> 32;
case 3 -> 52;
default -> 0;
};
รหัสนั้นง่ายขึ้นมากใช่ไหม? และอีกอย่างหนึ่ง: ตัวดำเนินการแลมบ์ดายังสามารถทำหน้าที่เป็นอะนาล็อกทั่วไปของลำไส้ใหญ่หลังจากนั้นจะมีทั้งบล็อกพร้อมการดำเนินการบางอย่าง:
int count = 2;
int value = switch (count) {
case 1 -> {
//some computational operations...
break 12;
}
case 2 -> {
//some computational operations...
break 32;
}
case 3 -> {
//some computational operations...
break 52;
}
default -> {
//some computational operations...
break 0;
}
};
แล้วถ้าในบางกรณีค่าที่ส่งคืนจะเท่ากันล่ะ? ปรากฎว่าจริงๆ แล้วเรามีกรณีเดียวกันสำหรับค่าที่ต่างกันบางค่า นี่คือวิธีที่สามารถย่อให้สั้นลงได้โดยใช้คุณสมบัติใหม่ใน Java 12:
int count = 2;
int value = switch (count) {
case 1, 3, 5 -> 12;
case 2, 4, 6 -> 52;
default -> 0;
};
สลับใน Java 13
ใน Java 13 วิธีที่สวิตช์ส่งคืนค่ามีการเปลี่ยนแปลง หากใน java 12 เราเขียนค่าที่ส่งคืนหลังตัวแบ่ง ซึ่งทำหน้าที่เป็นค่าส่งคืนสำหรับบล็อกสวิตช์ ตอนนี้เราจะคืนค่าโดยใช้คำว่าallowance มาดูกัน:int value = switch (count) {
case 1:
yield 12;
case 2:
yield 32;
case 3:
yield 52;
default:
yield 0;
};
ในขณะเดียวกันโค้ดที่เขียนด้วย Java 12 โดยใช้ตัวแบ่งเพื่อส่งคืนจะไม่คอมไพล์ (( จะใช้ตัวแบ่ง แต่ในสถานการณ์ที่เราไม่จำเป็นต้องส่งคืนสิ่งใด ๆ
ทั้งหมด
- ใช้ คำสั่ง caseเมื่อมีสาขามากกว่าสองสาขาเพื่อหลีกเลี่ยงไม่ให้โค้ดของคุณยุ่งเหยิงด้วยโครงสร้าง if
- อย่าลืมจบบล็อกลอจิคัลของแต่ละสาขาที่สอดคล้องกับค่าเฉพาะ (บล็อกตัวพิมพ์) ด้วยการเรียกพัก
- นอกจากประเภทพื้นฐานบางประเภทแล้ว คำสั่ง switch ยังสามารถใช้ ประเภท EnumและString เป็นนิพจน์ ได้ ด้วย
- จำ บล็อก เริ่มต้น - ใช้เพื่อจัดการค่าการเลือกที่ไม่ได้วางแผนไว้
- เพื่อเพิ่มประสิทธิภาพการทำงาน ให้ย้ายสาขาโค้ดที่มีตัวเลือกที่พบบ่อยที่สุดไปยังจุดเริ่มต้นของบล็อกสวิตช์
- อย่าหลงไปกับ "การเพิ่มประสิทธิภาพ" ด้วยการลบตัวแบ่งที่ส่วนท้ายของ บล็อกการเลือก เคสออก - โค้ดดังกล่าวเข้าใจยาก และเป็นผลให้บำรุงรักษาได้ยากในระหว่างการพัฒนา
GO TO FULL VERSION