ทำไมฉันไม่สามารถใช้คำสั่ง switch บน String ได้


1004

ฟังก์ชั่นนี้จะถูกเพิ่มเข้าไปในเวอร์ชั่น Java ภายหลังหรือไม่?

บางคนสามารถอธิบายได้ว่าทำไมฉันไม่สามารถทำสิ่งนี้ในขณะที่switchคำสั่งทางเทคนิคของ Java ทำงานได้หรือไม่


195
มันอยู่ใน SE 7 16 ปีหลังจากได้รับการร้องขอ download.oracle.com/javase/tutorial/java/nutsandbolts/ …
angryITguy

81
ดวงอาทิตย์ซื่อสัตย์ในการประเมินของพวกเขา: "Don't hold your breath."lol, bugs.sun.com/bugdatabase/view_bug.do?bug_id=1223179
raffian

3
@raffian ฉันคิดว่าเป็นเพราะเธอถอนหายใจสองครั้ง พวกเขาสายเกินไปที่จะตอบด้วยเช่นกันหลังจากเกือบ 10 ปี เธออาจจะบรรจุกล่องอาหารกลางวันให้ลูกหลานของเธอแล้ว
WeirdElfB0y

คำตอบ:


1003

คำสั่ง Switch กับStringcase ถูกนำไปใช้ในJava SE 7อย่างน้อย 16 ปีหลังจากที่ถูกร้องขอครั้งแรก ไม่มีเหตุผลที่ชัดเจนสำหรับการหน่วงเวลา แต่มีแนวโน้มว่าจะเกี่ยวกับประสิทธิภาพ

การใช้งานใน JDK 7

ขณะนี้คุณลักษณะดังกล่าวได้รับการติดตั้งjavac ด้วยกระบวนการ "ยกเลิกการชำระเงิน" ไวยากรณ์ที่สะอาดและมีระดับสูงโดยใช้Stringค่าคงที่ในcaseการประกาศจะถูกขยายในเวลาคอมไพล์เป็นรหัสที่ซับซ้อนมากขึ้นหลังจากรูปแบบ รหัสผลลัพธ์ใช้คำแนะนำ JVM ที่มีอยู่เสมอ

A switchพร้อมStringเคสถูกแปลเป็นสองสวิตช์ระหว่างการคอมไพล์ ครั้งแรกที่จับคู่แต่ละสตริงกับจำนวนเต็มเฉพาะตำแหน่งของมันในสวิตช์เดิม ทำได้โดยการสลับรหัสแฮชของป้ายกำกับก่อน กรณีที่เกี่ยวข้องคือifคำสั่งที่ทดสอบความเท่าเทียมกันของสตริง; ถ้ามีการชนกันบนกัญชา, if-else-ifการทดสอบเป็นซ้อน สวิตช์ที่สองสะท้อนว่าในซอร์สโค้ดต้นฉบับ แต่แทนที่ฉลากเคสด้วยตำแหน่งที่สอดคล้องกัน กระบวนการสองขั้นตอนนี้ทำให้ง่ายต่อการรักษาการควบคุมการไหลของสวิตช์เดิม

สวิทช์ใน JVM

สำหรับความลึกด้านเทคนิคเพิ่มเติมswitchคุณสามารถอ้างถึงข้อกำหนด JVM ซึ่งการรวบรวมคำสั่งสวิตช์อธิบายไว้ สรุปมีคำแนะนำ JVM ที่แตกต่างกันสองคำที่สามารถใช้สำหรับสวิตช์ได้ขึ้นอยู่กับความแตกต่างของค่าคงที่ที่ใช้โดยเคส ทั้งสองขึ้นอยู่กับการใช้ค่าคงที่จำนวนเต็มสำหรับแต่ละกรณีเพื่อดำเนินการอย่างมีประสิทธิภาพ

หากค่าคงที่หนาแน่นพวกเขาจะใช้เป็นดัชนี (หลังจากลบค่าต่ำสุด) ลงในตารางของพอยน์เตอร์คำสั่ง - tableswitchคำสั่ง

หากค่าคงที่เบาบางจะทำการค้นหาแบบไบนารีสำหรับกรณีที่ถูกต้องนั่นคือlookupswitchคำสั่ง

ในการกำจัดวัตถุa switchบนStringคำแนะนำทั้งสองมีแนวโน้มที่จะใช้ lookupswitchเหมาะสำหรับสวิทช์ครั้งแรกในรหัสกัญชาเพื่อหาสิ่งที่ตำแหน่งเดิมของคดี tableswitchลำดับส่งผลให้เป็นแบบธรรมชาติสำหรับ

คำแนะนำทั้งสองต้องการค่าคงที่จำนวนเต็มที่กำหนดให้แต่ละกรณีเพื่อจัดเรียงในเวลาคอมไพล์ ที่รันไทม์ในขณะที่O(1)ประสิทธิภาพtableswitchโดยทั่วไปจะดูดีกว่าO(log(n))ประสิทธิภาพของlookupswitchมันก็ต้องมีการวิเคราะห์บางอย่างเพื่อตรวจสอบว่าตารางมีความหนาแน่นเพียงพอที่จะปรับการแลกเปลี่ยนพื้นที่เวลา Bill Venners เขียนบทความที่ยอดเยี่ยมซึ่งครอบคลุมเนื้อหานี้อย่างละเอียดยิ่งขึ้นพร้อมกับการดูคำแนะนำการควบคุมการไหลของ Java อื่น ๆ

ก่อน JDK 7

ก่อนหน้า JDK 7 enumสามารถประมาณStringสวิตช์ที่ใช้ วิธีนี้ใช้วิธีสแตติกที่valueOfสร้างขึ้นโดยคอมไพเลอร์ในทุกenumประเภท ตัวอย่างเช่น:

Pill p = Pill.valueOf(str);
switch(p) {
  case RED:  pop();  break;
  case BLUE: push(); break;
}

26
มันอาจจะเร็วกว่าหากใช้ If-Else-If แทนที่จะใช้แฮชสำหรับสวิตช์แบบสตริง ฉันพบว่าพจนานุกรมมีราคาค่อนข้างแพงเมื่อเก็บของเพียงไม่กี่รายการ
Jonathan Allen

84
if-elseif-elseif-elseif-else อาจเร็วกว่า แต่ฉันจะลบโค้ดที่สะอาดกว่า 99 เท่าจาก 100 สตริงที่ไม่เปลี่ยนรูปแคชของแฮชโค้ดดังนั้น "คำนวณ" แฮชนั้นเร็ว จะต้องมีรหัสโปรไฟล์เพื่อพิจารณาว่ามีประโยชน์อะไร
erickson

21
เหตุผลที่ให้เทียบกับการเพิ่มสวิทช์ (สตริง) คือมันไม่เป็นไปตามการรับประกันประสิทธิภาพที่คาดหวังจากคำสั่ง switch () พวกเขาไม่ต้องการที่จะ "ทำให้เข้าใจผิด" นักพัฒนา ตรงไปตรงมาฉันไม่คิดว่าพวกเขาควรรับประกันประสิทธิภาพของสวิตช์ () เพื่อเริ่มต้น
Gili

2
หากคุณเพียงแค่ใช้Pillเพื่อดำเนินการบางอย่างตามที่strฉันจะยืนยันว่า - อื่นเป็นที่นิยมเพราะมันช่วยให้คุณสามารถจัดการstrค่านอกช่วง RED, BLUE โดยไม่ต้องจับยกเว้นvalueOfหรือตรวจสอบการแข่งขันกับชื่อของตนเอง การแจงนับแต่ละประเภทซึ่งเพิ่งเพิ่มค่าใช้จ่ายที่ไม่จำเป็น จากประสบการณ์ของฉันมันเป็นเพียงความรู้สึกที่จะใช้valueOfในการแปลงเป็นการแจงนับหากจำเป็นต้องมีการแสดงค่า typesype ที่เป็นความลับในภายหลัง
MilesHampson

ฉันสงสัยว่าคอมไพเลอร์ใช้ความพยายามในการทดสอบว่ามีคู่ของตัวเลขใด ๆ (x, y) หรือไม่ซึ่งชุดของค่า(hash >> x) & ((1<<y)-1)จะให้ค่าที่แตกต่างกันสำหรับสตริงทุกอันที่hashCodeแตกต่างกันและ(1<<y)น้อยกว่าสองเท่าของจำนวนสตริง (หรือที่ อย่างน้อยก็ไม่ยิ่งใหญ่ไปกว่านั้น)
supercat

125

หากคุณมีสถานที่ในรหัสของคุณที่คุณสามารถเปิดใช้งานสตริงได้ก็ควรจะปรับโครงสร้างสตริงให้ดีขึ้นเพื่อระบุจำนวนของค่าที่เป็นไปได้ซึ่งคุณสามารถเปิดได้ แน่นอนว่าคุณ จำกัด ค่าที่อาจเป็นไปได้ของ Strings ที่คุณสามารถมีได้ในการระบุซึ่งอาจเป็นหรือไม่ต้องการก็ได้

แน่นอนการแจงนับของคุณอาจมีรายการสำหรับ 'อื่น ๆ ' และวิธี fromString (String) จากนั้นคุณอาจมี

ValueEnum enumval = ValueEnum.fromString(myString);
switch (enumval) {
   case MILK: lap(); break;
   case WATER: sip(); break;
   case BEER: quaff(); break;
   case OTHER: 
   default: dance(); break;
}

4
เทคนิคนี้ยังช่วยให้คุณตัดสินใจเกี่ยวกับปัญหาต่างๆเช่นความไม่สะดวกของตัวพิมพ์เล็ก ๆ , นามแฝง, ฯลฯ แทนที่จะพึ่งพานักออกแบบภาษาที่จะเกิดขึ้นกับโซลูชัน "หนึ่งขนาดเหมาะกับทุกคน"
Darron

2
เห็นด้วยกับ JeeBee หากคุณเปลี่ยนสายอาจต้อง enum สตริงมักจะแสดงถึงบางสิ่งบางอย่างไปยังอินเทอร์เฟซ (ผู้ใช้หรืออย่างอื่น) ที่อาจมีการเปลี่ยนแปลงในอนาคตดังนั้นควรแทนที่ด้วย enums
hhafez

18
ดูxefer.com/2006/12/switchonstringสำหรับวิธีการนี้
David Schmitt

@DavidSchmitt บทความมีข้อบกพร่องสำคัญอย่างหนึ่ง มันจับข้อยกเว้นทั้งหมดแทนที่จะเป็นที่ถูกโยนโดย methode
M. Mimpen

91

ต่อไปนี้เป็นตัวอย่างที่สมบูรณ์ตามการโพสต์ของ JeeBee โดยใช้ java enum แทนการใช้วิธีการที่กำหนดเอง

โปรดทราบว่าใน Java SE 7 และใหม่กว่าคุณสามารถใช้วัตถุ String ในการแสดงออกของคำสั่งเปลี่ยนแทน

public class Main {

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) {

      String current = args[0];
      Days currentDay = Days.valueOf(current.toUpperCase());

      switch (currentDay) {
          case MONDAY:
          case TUESDAY:
          case WEDNESDAY:
              System.out.println("boring");
              break;
          case THURSDAY:
              System.out.println("getting better");
          case FRIDAY:
          case SATURDAY:
          case SUNDAY:
              System.out.println("much better");
              break;

      }
  }

  public enum Days {

    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
  }
}

26

สวิตช์ที่ใช้จำนวนเต็มสามารถปรับให้เหมาะกับโค้ดที่มีประสิทธิภาพมาก สวิทช์ที่ยึดตามชนิดข้อมูลอื่นสามารถรวบรวมได้กับชุดคำสั่ง if () เท่านั้น

ด้วยเหตุนี้ C & C ++ จึงอนุญาตเฉพาะการสลับกับประเภทจำนวนเต็มเนื่องจากไม่มีประโยชน์กับประเภทอื่น ๆ

นักออกแบบของ C # ตัดสินใจว่าสไตล์นั้นสำคัญแม้ว่าจะไม่มีประโยชน์ก็ตาม

ผู้ออกแบบของ Java คิดว่าเหมือนนักออกแบบของ C


26
สวิตช์ที่ยึดตามวัตถุแฮชใด ๆ อาจถูกนำไปใช้อย่างมีประสิทธิภาพโดยใช้ตารางแฮช - ดู. NET ดังนั้นเหตุผลของคุณไม่ถูกต้องสมบูรณ์
Konrad Rudolph

ใช่และนี่คือสิ่งที่ฉันไม่เข้าใจ ในระยะยาวแล้วพวกเขากลัวว่าวัตถุที่ได้รับการบดบังจะมีราคาแพงหรือ
Alex Beardsley

3
@Nalandial: จริง ๆ แล้วมีความพยายามเล็กน้อยในส่วนของคอมไพเลอร์มันไม่แพงเลยเพราะเมื่อรู้ว่าชุดของสตริงมันค่อนข้างง่ายที่จะสร้างแฮชที่สมบูรณ์แบบ (ซึ่งไม่ได้ทำโดย. NET อาจไม่คุ้มค่ากับความพยายามทั้ง)
Konrad Rudolph

3
@Nalandial & @Konrad Rudolph - ในขณะที่ hashing a String (เนื่องจากเป็นลักษณะที่ไม่เปลี่ยนรูปแบบ) ดูเหมือนจะเป็นวิธีการแก้ปัญหานี้คุณต้องจำไว้ว่าวัตถุที่ไม่ใช่ครั้งสุดท้ายทั้งหมดจะสามารถแทนที่ฟังก์ชัน hashing ได้ สิ่งนี้ทำให้ยากในการรวบรวมเวลาเพื่อให้แน่ใจว่ามีความสอดคล้องในสวิตช์
martinatime

2
คุณยังสามารถสร้าง DFA ให้ตรงกับสตริงได้ (เช่นเดียวกับเอ็นจิ้นนิพจน์ทั่วไป) อาจจะมีประสิทธิภาพมากกว่าการบีบแตร
Nate CK

19

ตัวอย่างของการStringใช้โดยตรงตั้งแต่ 1.7 อาจปรากฏขึ้นเช่นกัน:

public static void main(String[] args) {

    switch (args[0]) {
        case "Monday":
        case "Tuesday":
        case "Wednesday":
            System.out.println("boring");
            break;
        case "Thursday":
            System.out.println("getting better");
        case "Friday":
        case "Saturday":
        case "Sunday":
            System.out.println("much better");
            break;
    }

}

18

James Curran พูดอย่างย่อ ๆ ว่า: "สวิตช์ที่ใช้จำนวนเต็มสามารถปรับให้เหมาะกับโค้ดที่มีประสิทธิภาพได้มากสวิตช์ที่ใช้ชนิดข้อมูลอื่นสามารถรวบรวมได้เป็นชุดคำสั่ง if () เท่านั้นด้วยเหตุนี้ C & C ++ อนุญาตเฉพาะสวิตช์ที่เป็นประเภทจำนวนเต็มเท่านั้น เพราะมันไม่มีจุดหมายกับประเภทอื่น "

ความคิดเห็นของฉันและเป็นเพียงสิ่งนั้นคือทันทีที่คุณเริ่มเปลี่ยนสิ่งที่ไม่ใช่ภาษาดั้งเดิมคุณจะต้องเริ่มคิดถึง "เท่ากับ" กับ "==" การเปรียบเทียบสองสตริงแรกอาจเป็นขั้นตอนที่ค่อนข้างยาวซึ่งจะเป็นการเพิ่มปัญหาด้านประสิทธิภาพที่กล่าวถึงข้างต้น ประการที่สองหากมีการสลับกับสตริงจะมีความต้องการสำหรับการสลับบนสตริงโดยไม่สนใจขนาดตัวอักษรสลับกับสตริงพิจารณา / ละเว้นสถานที่การเปลี่ยนสตริงตาม regex .... ฉันจะอนุมัติการตัดสินใจที่ประหยัดเวลามากสำหรับ นักพัฒนาภาษาเสียค่าใช้จ่ายเล็กน้อยสำหรับโปรแกรมเมอร์


ในทางเทคนิคแล้ว regexes "switch" เนื่องจากมันเป็นเพียงเครื่องจักร พวกเขาเพียงแค่มีเพียงสอง "กรณี" และmatched not matched(ไม่คำนึงถึงสิ่งต่าง ๆ เช่น [ชื่อ] กลุ่ม / อื่น ๆ )
JAB

1
docs.oracle.com/javase/7/docs/technotes/guides/language/…สถานะ: คอมไพเลอร์ Java สร้าง bytecode ที่มีประสิทธิภาพมากขึ้นโดยทั่วไปจากคำสั่งเปลี่ยนที่ใช้วัตถุ String กว่าจากคำสั่งถ้าแล้วจึงอื่น
Wim Deblauwe

12

นอกเหนือจากข้อโต้แย้งที่ดีข้างต้นฉันจะเพิ่มผู้คนจำนวนมากในวันนี้ที่เห็นswitchว่าเป็นส่วนที่เหลือล้าสมัยของขั้นตอนที่ผ่านมาของ Java (กลับไปที่ครั้ง C)

ฉันไม่ได้แบ่งปันความคิดเห็นนี้อย่างเต็มที่ฉันคิดว่าswitchอาจมีประโยชน์ในบางกรณีอย่างน้อยก็เนื่องจากความเร็วของมันและอย่างไรก็ตามมันก็ยังดีกว่าชุดตัวเลขที่เรียงซ้อนที่else ifฉันเห็นในบางโค้ด ...

แต่จริงๆแล้วมันคุ้มค่าที่จะดูกรณีที่คุณต้องการสวิตช์และดูว่ามันไม่สามารถถูกแทนที่ด้วย OO ที่มากกว่านี้ได้ไหม ตัวอย่างเช่น enums ใน Java 1.5+, บางที HashTable หรือคอลเล็กชันอื่น ๆ (บางครั้งฉันเสียใจที่เราไม่มีฟังก์ชั่น (ไม่ระบุชื่อ) ในฐานะพลเมืองชั้นหนึ่งเช่นใน Lua - ซึ่งไม่มีสวิตช์ - หรือ JavaScript) หรือแม้กระทั่งหลากหลาย


"บางครั้งฉันเสียใจที่เราไม่มีฟังก์ชัน (ไม่ระบุชื่อ) ในฐานะพลเมืองชั้นหนึ่ง" นั่นไม่จริงอีกต่อไป
user8397947

@dorukayhan ใช่แน่นอน แต่คุณต้องการที่จะเพิ่มความคิดเห็นที่คำตอบทั้งหมดจากสิบปีที่ผ่านมาเพื่อบอกให้โลกรู้ว่าเราสามารถมีพวกเขาหากเราอัปเดตเป็น Java รุ่นใหม่กว่า? :-D
PhiLho

8

หากคุณไม่ได้ใช้ JDK7 หรือสูงกว่าคุณสามารถใช้hashCode()เพื่อจำลองมันได้ เพราะString.hashCode()มักจะส่งกลับค่าที่แตกต่างกันสำหรับสตริงที่แตกต่างกันและมักจะส่งกลับค่าเท่ากับสตริงเท่ากันมันมีความน่าเชื่อถือเป็นธรรม (สตริงที่แตกต่างกันสามารถผลิตกัญชารหัสเดียวกับ @Lii กล่าวถึงในการแสดงความคิดเห็นเช่น"FB"และ"Ea") ดูเอกสาร

ดังนั้นรหัสจะเป็นดังนี้:

String s = "<Your String>";

switch(s.hashCode()) {
case "Hello".hashCode(): break;
case "Goodbye".hashCode(): break;
}

intวิธีการที่คุณจะได้ในทางเทคนิคสลับบน

หรือคุณสามารถใช้รหัสต่อไปนี้:

public final class Switch<T> {
    private final HashMap<T, Runnable> cases = new HashMap<T, Runnable>(0);

    public void addCase(T object, Runnable action) {
        this.cases.put(object, action);
    }

    public void SWITCH(T object) {
        for (T t : this.cases.keySet()) {
            if (object.equals(t)) { // This means that the class works with any object!
                this.cases.get(t).run();
                break;
            }
        }
    }
}

5
สองสายอักขระที่แตกต่างกันสามารถมีแฮชโค้ดเดียวกันได้ดังนั้นหากคุณเปิดแฮชโค้ดอาจใช้กรณีตัวพิมพ์ใหญ่ผิด
Lii

@Lii ขอบคุณที่ชี้ให้เห็น! มันไม่น่าเป็นไปได้ แต่ฉันจะไม่เชื่อใจว่ามันใช้งานได้ "FB" และ "Ea" มีแฮชโค้ดเดียวกันดังนั้นจึงไม่สามารถหาการชนกันได้ รหัสที่สองน่าจะน่าเชื่อถือมากขึ้น
HyperNeutrino

ฉันประหลาดใจที่คอมไพล์นี้ตามที่caseมีให้ฉันคิดว่าเป็นค่าคงที่เสมอและString.hashCode()ไม่ใช่เช่นนั้น (แม้ว่าในการคำนวณการปฏิบัติไม่เคยเปลี่ยนแปลงระหว่าง JVMs)
StaxMan

@StaxMan น่าสนใจฉันไม่เคยหยุดที่จะสังเกตเห็นว่า แต่ใช่caseค่าข้อความไม่ต้องถูกกำหนดในเวลารวบรวมเพื่อให้ทำงานได้อย่างประณีต
HyperNeutrino

4

เป็นเวลาหลายปีแล้วที่เราได้ใช้ตัวประมวลผลล่วงหน้า (โอเพ่นซอร์ส) สำหรับเรื่องนี้

//#switch(target)
case "foo": code;
//#end

ไฟล์ที่ประมวลผลล่วงหน้ามีชื่อว่า Foo.jpp และประมวลผลเป็น Foo.java ด้วยสคริปต์ ant

ข้อดีคือมันถูกประมวลผลเป็น Java ที่รันบน 1.0 (แม้ว่าโดยทั่วไปแล้วเราจะสนับสนุนกลับไปที่ 1.4 เท่านั้น) นอกจากนี้การทำเช่นนี้ (สวิตช์สตริงจำนวนมาก) ทำได้ง่ายกว่าเมื่อเปรียบเทียบกับ fudging ด้วย enums หรือวิธีแก้ไขอื่น ๆ - รหัสนั้นง่ายกว่ามากในการอ่านบำรุงรักษาและเข้าใจ IIRC (ไม่สามารถให้สถิติหรือเหตุผลทางเทคนิค ณ จุดนี้) มันเร็วกว่า Java เทียบเท่าทั่วไป

ข้อเสียคือคุณไม่ได้แก้ไข Java ดังนั้นจึงมีเวิร์กโฟลว์เพิ่มขึ้นเล็กน้อย (แก้ไขประมวลผลคอมไพล์ / ทดสอบ) และ IDE จะเชื่อมโยงกลับไปที่ Java ซึ่งมีความซับซ้อนเล็กน้อย (สวิตช์กลายเป็นชุดของขั้นตอนตรรกะอื่น / ตรรกะ) และลำดับตัวเรือนสวิตช์ไม่ได้รับการปรับปรุง

ฉันไม่แนะนำสำหรับ 1.7+ แต่มีประโยชน์ถ้าคุณต้องการโปรแกรม Java ที่กำหนดเป้าหมาย JVM ก่อนหน้านี้ (เนื่องจาก Joe สาธารณะไม่ค่อยติดตั้งล่าสุด)

คุณจะได้รับจาก SVNหรือเรียกดูออนไลน์รหัส คุณจะต้องEBuildเพื่อสร้างมันตามที่เป็นอยู่


6
คุณไม่จำเป็นต้องใช้ 1.7 JVM ในการเรียกใช้โค้ดด้วยสวิตช์ String คอมไพเลอร์ 1.7 เปลี่ยนสวิตช์สตริงเป็นสิ่งที่ใช้รหัสไบต์ที่มีอยู่ก่อนหน้านี้
Dawood ibn Kareem

4

คำตอบอื่น ๆ ได้กล่าวว่าสิ่งนี้ถูกเพิ่มเข้ามาใน Java 7 และให้วิธีแก้ไขปัญหาสำหรับรุ่นก่อนหน้า คำตอบนี้พยายามที่จะตอบว่า "ทำไม"

Java เป็นปฏิกิริยาต่อความซับซ้อนของ C ++ มันถูกออกแบบมาให้เป็นภาษาที่เรียบง่ายสะอาดตา

String มีการจัดการกรณีพิเศษเล็กน้อยในภาษา แต่สำหรับฉันดูเหมือนว่านักออกแบบพยายามที่จะรักษาปริมาณของปลอกพิเศษและน้ำตาล syntactic ให้น้อยที่สุด

การสลับสายค่อนข้างซับซ้อนภายใต้ประทุนเนื่องจากสตริงไม่ใช่ประเภทดั้งเดิม มันไม่ใช่คุณสมบัติทั่วไปในขณะที่ Java ถูกออกแบบและไม่เหมาะกับการออกแบบที่เรียบง่าย โดยเฉพาะอย่างยิ่งเมื่อพวกเขาตัดสินใจที่จะไม่ใช้ตัวพิมพ์เล็ก == สำหรับสตริงมันจะแปลกไปหน่อยสำหรับกรณีที่ == ไม่ทำงาน

ระหว่าง 1.0 ถึง 1.4 ภาษานั้นค่อนข้างคงเดิม การปรับปรุงส่วนใหญ่ของจาวาอยู่ที่ด้านห้องสมุด

ทุกอย่างเปลี่ยนไปด้วย Java 5 ภาษาได้ถูกขยายออกไปอย่างมาก ส่วนขยายเพิ่มเติมตามมาในรุ่น 7 และ 8 ฉันคาดหวังว่าการเปลี่ยนแปลงทัศนคตินี้ได้รับแรงหนุนจากการเพิ่มขึ้นของ C #


การบรรยายเกี่ยวกับสวิตช์ (สตริง) เหมาะกับประวัติระยะเวลาบริบท cpp / cs
เอสเพรสโซ่

มันเป็นความผิดพลาดครั้งใหญ่ที่จะไม่ใช้คุณสมบัตินี้ทุกอย่างเป็นข้อแก้ตัวที่ถูก Java สูญเสียผู้ใช้หลายคนในช่วงหลายปีที่ผ่านมาเนื่องจากการขาดความก้าวหน้าและความดื้อรั้นของนักออกแบบที่จะไม่พัฒนาภาษา โชคดีที่พวกเขาเปลี่ยนทิศทางและทัศนคติอย่างสมบูรณ์หลังจาก JDK7
firephil

0

JEP 354: สลับนิพจน์ (ดูตัวอย่าง)ใน JDK-13 และ JEP 361: เปลี่ยนนิพจน์ (มาตรฐาน)ใน JDK-14 จะขยายคำสั่ง switchเพื่อให้สามารถใช้เป็นนิพจน์ได้

ตอนนี้คุณสามารถ:

  • โดยตรงตัวแปรกำหนดจากการแสดงออกของสวิทช์ ,
  • ใช้สวิตช์รูปแบบใหม่ของฉลาก ( case L ->):

    รหัสทางด้านขวาของฉลากสวิตช์ "case L ->" ถูก จำกัด ให้เป็นนิพจน์บล็อกหรือ (เพื่อความสะดวก) คำสั่งส่งข้อความ

  • ใช้หลายค่าคงที่ต่อกรณีคั่นด้วยเครื่องหมายจุลภาค
  • และยังไม่มีการแบ่งค่าอีกต่อไป:

    เพื่อให้ได้ค่าจากนิพจน์สวิตช์, breakด้วยคำสั่ง value จะถูกดร็อปไว้ในyieldข้อความสั่ง

ดังนั้นตัวอย่างจากคำตอบ ( 1 , 2 ) อาจมีลักษณะเช่นนี้:

  public static void main(String[] args) {
    switch (args[0]) {
      case "Monday", "Tuesday", "Wednesday" ->  System.out.println("boring");
      case "Thursday" -> System.out.println("getting better");
      case "Friday", "Saturday", "Sunday" -> System.out.println("much better");
    }

-2

ไม่สวยมาก แต่นี่เป็นอีกวิธีสำหรับ Java 6 และซอลเบลโลว์:

String runFct = 
        queryType.equals("eq") ? "method1":
        queryType.equals("L_L")? "method2":
        queryType.equals("L_R")? "method3":
        queryType.equals("L_LR")? "method4":
            "method5";
Method m = this.getClass().getMethod(runFct);
m.invoke(this);

-3

มันเป็นเรื่องง่ายใน Groovy; ฉันฝัง jar Groovy และสร้างgroovyคลาสยูทิลิตี้เพื่อทำสิ่งเหล่านี้ทั้งหมดและอีกมากมายที่ฉันพบว่าน่ารำคาญใน Java (เนื่องจากฉันติดอยู่กับ Java 6 ในองค์กร)

it.'p'.each{
switch (it.@name.text()){
   case "choclate":
     myholder.myval=(it.text());
     break;
     }}...

9
@SSpoke เพราะนี่เป็นคำถามเกี่ยวกับจาวาและคำตอบของ Groovy เป็นหัวข้อนอกเรื่องและปลั๊กที่ไม่มีประโยชน์
Martin

12
แม้แต่ในบ้าน SW ขนาดใหญ่ที่อนุรักษ์นิยม Groovy ก็ใช้งานร่วมกับ Java JVM ให้สภาพแวดล้อมที่ไม่เชื่อเรื่องภาษามากกว่าภาษาในปัจจุบันเพื่อผสมผสานและใช้กระบวนทัศน์การเขียนโปรแกรมที่เกี่ยวข้องมากที่สุดสำหรับการแก้ปัญหา ดังนั้นบางทีตอนนี้ฉันควรเพิ่ม snippet ใน Clojure เพื่อรวบรวม downvotes เพิ่มเติม :) ...
Alex Punnen

1
นอกจากนี้ไวยากรณ์ทำงานอย่างไร ฉันเดา Groovy เป็นภาษาการเขียนโปรแกรมที่แตกต่างกัน ... ขอโทษ ฉันไม่รู้อะไรเกี่ยวกับ Groovy
HyperNeutrino

-4

เมื่อคุณใช้ Intellij ดูที่:

ไฟล์ -> โครงสร้างโครงการ -> โครงการ

ไฟล์ -> โครงสร้างโครงการ -> โมดูล

เมื่อคุณมีหลายโมดูลตรวจสอบให้แน่ใจว่าคุณตั้งค่าระดับภาษาที่ถูกต้องในแท็บโมดูล


1
ไม่แน่ใจว่าคำตอบของคุณเกี่ยวข้องกับคำถามอย่างไร เขาถามว่าเพราะเหตุใดจึงไม่มีคำสั่งสตริงสวิตช์ดังต่อไปนี้: String mystring = "something"; switch (mystring) {case "some" sysout ("got here"); . . }
Deepak Agarwal

-8
public class StringSwitchCase { 

    public static void main(String args[]) {

        visitIsland("Santorini"); 
        visitIsland("Crete"); 
        visitIsland("Paros"); 

    } 

    public static void visitIsland(String island) {
         switch(island) {
          case "Corfu": 
               System.out.println("User wants to visit Corfu");
               break; 
          case "Crete": 
               System.out.println("User wants to visit Crete");
               break; 
          case "Santorini": 
               System.out.println("User wants to visit Santorini");
               break; 
          case "Mykonos": 
               System.out.println("User wants to visit Mykonos");
               break; 
         default: 
               System.out.println("Unknown Island");
               break; 
         } 
    } 

} 

8
OP ไม่ได้ถามว่าจะเปิดสตริงอย่างไร เขา / เธอกำลังถามว่าทำไมเขา / เธอถึงไม่สามารถทำได้เนื่องจากข้อ จำกัด ด้านไวยากรณ์ก่อน JDK7
HyperNeutrino
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.