Sử dụng hai giá trị cho một câu lệnh trường hợp chuyển đổi


295

Trong mã của tôi, chương trình thực hiện một cái gì đó tùy thuộc vào văn bản được nhập bởi người dùng. Mã của tôi trông như:

switch (name) {
        case text1: {
            //blah
            break;
        }
        case text2: {
            //blah
            break;
        }
        case text3: {
            //blah
            break;
        }
        case text4: {
            //blah
            break;
        }

Tuy nhiên, mã bên trong các trường hợp text1text4 là như nhau. Do đó, tôi đã tự hỏi nếu tôi có thể thực hiện một cái gì đó như

case text1||text4: {
            //blah
            break;
        }

Tôi biết rằng ||toán tử sẽ không hoạt động trong báo cáo trường hợp nhưng tôi có thể sử dụng một cái gì đó tương tự.


32
Là một câu hỏi cơ bản làm cho nó nếu bất cứ điều gì có thể dễ dàng hơn cho upvote nếu nó không phải là một bản sao như nó hữu ích rộng rãi. Và nó là thứ gì đó không xảy ra với tôi nhất có thể nhưng bây giờ tôi nhận ra nó rõ ràng rõ ràng. Vì vậy, tất cả trong một câu hỏi và trả lời khá tuyệt vời
Richard Tingle

1
@RichardTingle - bạn có quen thuộc với Thiết bị của Duff không - en.wikipedia.org/wiki/Duff%27s_device
user93353

4
"Tại sao rất nhiều upvote? Tìm kiếm" java switch "trên internet và đọc một trong hàng ngàn lời giải thích." <- bạn nghĩ tôi đang làm gì?
Brendan

4
Tôi thực sự đã tìm kiếm "nhiều trường hợp trong một dòng java" và câu hỏi và trả lời này là kết quả đầu tiên.
domenix

1
Bản demo chuyển đổi trong câu trả lời được chọn có thể được chỉnh sửa lại khi JDK-12 đã tích hợp JEP-325. :)
Naman

Câu trả lời:


555

Bạn có thể sử dụng có cả hai CASEcâu như sau.

  case text1: 
  case text4:{
            //blah
            break;
        }

XEM VÍ DỤ NÀY: Ví dụ mã tính toán số ngày trong một tháng cụ thể:

class SwitchDemo {
    public static void main(String[] args) {

        int month = 2;
        int year = 2000;
        int numDays = 0;

        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                numDays = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                numDays = 30;
                break;
            case 2:
                if (((year % 4 == 0) && 
                     !(year % 100 == 0))
                     || (year % 400 == 0))
                    numDays = 29;
                else
                    numDays = 28;
                break;
            default:
                System.out.println("Invalid month.");
                break;
        }
        System.out.println("Number of Days = "
                           + numDays);
    }
}

Đây là đầu ra từ mã:

Number of Days = 29

FALLTHROUGH:

Một điểm quan tâm khác là tuyên bố phá vỡ. Mỗi câu lệnh ngắt kết thúc câu lệnh chuyển đổi kèm theo. Luồng điều khiển tiếp tục với câu lệnh đầu tiên sau khối chuyển đổi. Các câu lệnh break là cần thiết bởi vì không có chúng, các câu lệnh trong khối chuyển đổifall through : Tất cả các câu lệnh sau nhãn trường hợp khớp được thực hiện theo trình tự, bất kể biểu thức của nhãn trường hợp tiếp theo, cho đến khi gặp câu lệnh break.

VÍ DỤ MÃ:

public class SwitchFallThrough {

    public static void main(String[] args) {
        java.util.ArrayList<String> futureMonths =
            new java.util.ArrayList<String>();

        int month = 8;

        switch (month) {
            case 1:  futureMonths.add("January");
            case 2:  futureMonths.add("February");
            case 3:  futureMonths.add("March");
            case 4:  futureMonths.add("April");
            case 5:  futureMonths.add("May");
            case 6:  futureMonths.add("June");
            case 7:  futureMonths.add("July");
            case 8:  futureMonths.add("August");
            case 9:  futureMonths.add("September");
            case 10: futureMonths.add("October");
            case 11: futureMonths.add("November");
            case 12: futureMonths.add("December");
            default: break;
        }

        if (futureMonths.isEmpty()) {
            System.out.println("Invalid month number");
        } else {
            for (String monthName : futureMonths) {
               System.out.println(monthName);
            }
        }
    }
}

Đây là đầu ra từ mã:

August
September
October
November
December

Sử dụng Chuỗi trong Báo cáo chuyển đổi

Trong Java SE 7 trở lên, bạn có thể sử dụng một đối tượng String trong biểu thức của câu lệnh switch. Ví dụ mã sau đây, hiển thị số tháng dựa trên giá trị của Chuỗi có tên tháng:

public class StringSwitchDemo {

    public static int getMonthNumber(String month) {

        int monthNumber = 0;

        if (month == null) {
            return monthNumber;
        }

        switch (month.toLowerCase()) {
            case "january":
                monthNumber = 1;
                break;
            case "february":
                monthNumber = 2;
                break;
            case "march":
                monthNumber = 3;
                break;
            case "april":
                monthNumber = 4;
                break;
            case "may":
                monthNumber = 5;
                break;
            case "june":
                monthNumber = 6;
                break;
            case "july":
                monthNumber = 7;
                break;
            case "august":
                monthNumber = 8;
                break;
            case "september":
                monthNumber = 9;
                break;
            case "october":
                monthNumber = 10;
                break;
            case "november":
                monthNumber = 11;
                break;
            case "december":
                monthNumber = 12;
                break;
            default: 
                monthNumber = 0;
                break;
        }

        return monthNumber;
    }

    public static void main(String[] args) {

        String month = "August";

        int returnedMonthNumber =
            StringSwitchDemo.getMonthNumber(month);

        if (returnedMonthNumber == 0) {
            System.out.println("Invalid month");
        } else {
            System.out.println(returnedMonthNumber);
        }
    }
}

Đầu ra từ mã này là 8.

TỪ Tài liệu Java


ồ được thôi. Điều đó thật dễ dàng. Không biết tôi có thể làm điều đó
Ankush

18
Điều đáng nói là tính năng ngôn ngữ này được gọi là dự phòng. Các trường hợp không breakcó cơ bản được gắn với khối trường hợp tiếp theo trực quan bên dưới, do đó rơi vào.
Hoàng đế Orionii

5
@ Kobor42 trước tiên hãy tìm hiểu cách nói chuyện trong các trang web công cộng. Mọi đề xuất của bạn đều giúp ích như thế nào. Cảm ơn
PSR

1
@ Kobor42 Làm thế nào về: Tại sao bạn đã sử dụng định dạng đó? Đặt các trường hợp khủng khiếp làm cho mã ít đọc hơn và thường được coi là thực hành xấu [Tham khảo tùy chọn nhưng mong muốn]. Tôi luôn cảm thấy rằng các câu lệnh chuyển đổi là một định dạng đặc biệt dễ đọc nhưng được trình bày theo cách này khiến chúng mất tất cả.
Richard Tingle

2
Bản demo chuyển đổi có thể được phát lại ngay bây giờ khi JDK-12 đã tích hợp JEP-325. :)
Naman


27

Các casegiá trị chỉ là các điểm "goto" không mã hóa có thể chia sẻ cùng một điểm nhập:

case text1:
case text4: 
    //blah
    break;

Lưu ý rằng niềng răng là dư thừa.


@trig lol. Gần đây tôi đang làm điều đó rất nhiều - đổ lỗi cho việc gõ ngón tay cái iPhone. Chúc mừng
Bohemian

21

Cứ làm đi

case text1: case text4: 
     do stuff;
     break;

15

Với sự tích hợp của JEP 325: Express Expressions (Bản xem trước) trong các bản dựng truy cập sớm của JDK-12, giờ đây người ta có thể sử dụng hình thức mới của nhãn chuyển đổi là: -

case text1, text4 -> {
     //blah
} 

hoặc để viết lại bản demo từ một trong những câu trả lời , đại loại như: -

public class RephraseDemo {

    public static void main(String[] args) {
        int month = 9;
        int year = 2018;
        int numDays = 0;

        switch (month) {
            case 1, 3, 5, 7, 8, 10, 12 ->{
                numDays = 31;
            }
            case 4, 6, 9, 11 ->{
                numDays = 30;
            }
            case 2 ->{
                if (((year % 4 == 0) &&
                        !(year % 100 == 0))
                        || (year % 400 == 0))
                    numDays = 29;
                else
                    numDays = 28;
            }
            default ->{
                System.out.println("Invalid month.");

            }
        }
        System.out.println("Number of Days = " + numDays);
    }
}

Đây là cách bạn có thể dùng thử - Biên dịch tính năng xem trước JDK12 với Maven


6

Các dấu ngoặc là không cần thiết. Cứ làm đi

case text1:
case text4:
  doSomethingHere();
  break;
case text2:
  doSomethingElse()
  break;

Nếu bất cứ ai tò mò, điều này được gọi là một trường hợp lạc hậu. Khả năng để làm điều này là lý do tại sao break;cần thiết để kết thúc báo cáo trường hợp. Để biết thêm thông tin, hãy xem bài viết trên wikipedia http://en.wikipedia.org/wiki/Switch_statement .


5

Câu fallthroughtrả lời của người khác là những câu hỏi hay.

Tuy nhiên, một cách tiếp cận khác sẽ là trích xuất các phương thức ra khỏi nội dung của các báo cáo trường hợp của bạn và sau đó chỉ cần gọi phương thức thích hợp từ mỗi trường hợp.

Trong ví dụ dưới đây, cả trường hợp 'text1' và trường hợp 'text4' đều hoạt động giống nhau:

switch (name) {
        case text1: {
            method1();
            break;
        }
        case text2: {
            method2();
            break;
        }
        case text3: {
            method3();
            break;
        }
        case text4: {
            method1();
            break;
        }

Cá nhân tôi thấy phong cách viết báo cáo trường hợp này dễ bảo trì hơn và dễ đọc hơn một chút, đặc biệt khi các phương thức bạn gọi có tên mô tả tốt.


1
Sẽ không thể duy trì nhiều hơn nếu text1text4sẽ CỐ GẮNG làm điều tương tự, bất kể thay đổi trong tương lai. Nếu chúng phải luôn được liên kết, thực hiện thay đổi trong trường hợp text1(nghĩa là thay đổi phương thức mà nó gọi) sẽ yêu cầu thay đổi text4. Trong trường hợp này rõ ràng là không thể bảo trì nhiều hơn. Nó phụ thuộc vào tình hình.
Nick Freeman

1
Tôi sẽ nói rằng phương thức này có lẽ nên được kết hợp với cách khác, vì các câu lệnh chuyển đổi không phải là (IMHO) cấu trúc lập trình đẹp nhất.
Nick Freeman

5

Rơi qua cách tiếp cận là cách tốt nhất tôi cảm thấy.

case text1:
case text4: {
        //Yada yada
        break;
} 


4

Các giá trị trường hợp chỉ là các điểm "goto" không mã hóa có thể chia sẻ cùng một điểm nhập:

case text1:
case text4: {
// Làm gì đó
phá vỡ;
}

Lưu ý rằng niềng răng là dư thừa.


1

JEP 354: Biểu thức chuyển đổi (Bản xem trước) trong JDK-13 và JEP 361: Biểu thức chuyển đổi (Tiêu chuẩn) trong JDK-14 sẽ mở rộng câu lệnh chuyển đổi để có thể được sử dụng làm biểu thức .

Bây giờ bạn có thể:

  • gán biến trực tiếp từ biểu thức chuyển đổi ,
  • sử dụng hình thức mới của nhãn chuyển đổi (case L -> ):

    Mã ở bên phải của nhãn chuyển đổi "trường hợp L ->" bị hạn chế là biểu thức, khối hoặc (để thuận tiện) cho câu lệnh ném.

  • sử dụng nhiều hằng số cho mỗi trường hợp, cách nhau bằng dấu phẩy,
  • và cũng không có thêm giá trị phá vỡ :

    Để mang lại một giá trị từ một biểu thức chuyển đổi, breakcâu lệnh with value được bỏ theo hướng có lợi cho yieldcâu lệnh.

Vì vậy, bản demo từ một trong những câu trả lời có thể trông như thế này:

public class SwitchExpression {

  public static void main(String[] args) {
      int month = 9;
      int year = 2018;
      int numDays = switch (month) {
        case 1, 3, 5, 7, 8, 10, 12 -> 31;
        case 4, 6, 9, 11 -> 30;
        case 2 -> {
          if (java.time.Year.of(year).isLeap()) {
            System.out.println("Wow! It's leap year!");
            yield 29;
          } else {
            yield 28;
          }
        }
        default -> {
          System.out.println("Invalid month.");
          yield 0;
        }
      };
      System.out.println("Number of Days = " + numDays);
  }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.