JavaRush /Blog Java /Random-VI /Câu lệnh chuyển đổi trong Java

Câu lệnh chuyển đổi trong Java

Xuất bản trong nhóm
Hãy tưởng tượng bạn đang đứng ở một ngã ba, giống như một anh hùng trong bức tranh nổi tiếng. Nếu bạn đi bên trái, bạn sẽ mất ngựa; nếu bạn đi bên phải, bạn sẽ thu được kiến ​​thức. Làm thế nào để lập trình một tình huống như vậy? Rất có thể bạn đã biết rằng chúng ta đưa ra lựa chọn như vậy bằng cách sử dụng cấu trúc if-thenif-then-else .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
Điều gì sẽ xảy ra nếu không có hai bản nhạc như vậy mà là 10 bản nhạc? Có một con đường “sang phải”, “sang trái một chút”, “sang trái một chút”, v.v., với số lượng 10 miếng? Hãy tưởng tượng mã if-then-else của bạn sẽ phát triển như thế nào trong phiên bản này!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
Vì vậy, bạn không có một nhánh điều kiện mà có nhiều điều kiện, chẳng hạn như 10 (điều quan trọng ở đây là số lượng nhánh có hạn). Đối với những tình huống như vậy, có một toán tử lựa chọn đặc biệt - switch case java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
Thứ tự thực hiện trong câu lệnh như sau:
  • SelectionExpression được đánh giá. Tiếp theo, câu lệnh switch so sánh biểu thức kết quả với Giá trị tiếp theo (theo thứ tự được liệt kê).
  • Nếu SelectExpression khớp với Giá trị thì mã theo sau dấu hai chấm sẽ được thực thi.
  • Nếu gặp phải cấu trúc break thì quyền điều khiển sẽ được chuyển ra ngoài lệnh switch.
  • Nếu không tìm thấy kết quả khớp nào giữa ExpressionForSelection và Values ​​thì điều khiển sẽ được chuyển sang DefaultSelectionCode.
Điểm quan trọng
  • Loại SelectionExpression cho câu lệnh lựa chọn chuyển đổi trong Java phải là một trong các loại sau:

    • byte , ngắn , char , int .
    • Các hàm bao của chúng là Byte , Short , Character , Integer .
    • Chuỗi (kể từ Java 7).
    • Bảng liệt kê ( Enum ).
  • Khối mặc định là tùy chọn, sau đó nếu SelectionExpression và Values ​​không khớp nhau thì sẽ không có hành động nào được thực hiện.
  • break là tùy chọn; nếu nó không xuất hiện, mã sẽ tiếp tục thực thi (bỏ qua các so sánh tiếp theo của các giá trị trong khối case) cho đến khi breakgặp câu lệnh switch đầu tiên hoặc cho đến khi kết thúc.
  • nếu cần thực thi cùng một mã cho một số tùy chọn lựa chọn, để tránh trùng lặp, chúng tôi chỉ ra một số giá trị tương ứng ở phía trước nó trong các khối chữ liên tiếp .

Hãy chuyển sang thực hành sử dụng câu lệnh switch trong Java

Đừng lo lắng, chúng ta đã xong phần lý thuyết và sau những ví dụ khác, mọi thứ sẽ trở nên rõ ràng hơn nhiều. Vậy hãy bắt đầu. Chúng ta hãy xem một ví dụ từ thiên văn học về các hành tinh trong hệ mặt trời. Theo các quy định quốc tế mới nhất, chúng tôi sẽ loại trừ Sao Diêm Vương (do đặc tính quỹ đạo của nó). Chúng ta hãy nhớ rằng các hành tinh của chúng ta được định vị tính từ Mặt trời theo trình tự sau: Sao Thủy, Sao Kim, Trái Đất, Sao Hỏa, Sao Mộc, Sao Thổ, Sao Thiên Vương và Sao Hải Vương. Hãy tạo một phương thức Java nhận đầu vào là số sê-ri của hành tinh (tương ứng với khoảng cách từ Mặt trời) và đầu ra tạo ra thành phần chính của bầu khí quyển của hành tinh này dưới dạng Danh sách <String> . Hãy để tôi nhắc bạn rằng một số hành tinh có thành phần bầu khí quyển tương tự. Do đó, Sao Kim và Sao Hỏa chứa chủ yếu là carbon dioxide, Sao Mộc và Sao Thổ bao gồm hydro và heli, còn Sao Thiên Vương và Sao Hải Vương, ngoài cặp khí cuối cùng, còn có khí mê-tan. Chức năng của chúng tôi:
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;
}
Xin lưu ý: chúng tôi đã so sánh cùng một mã với các hành tinh có thành phần khí quyển giống hệt nhau. Và chúng tôi đã làm điều này bằng cách sử dụng các cấu trúc trường hợp liên tiếp . Vì vậy, nếu chúng ta muốn biết thành phần bầu khí quyển của hành tinh quê nhà, chúng ta gọi phương thức của mình với tham số 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
Thử nghiệm với break Điều gì xảy ra nếu chúng ta loại bỏ tất cả các câu lệnh break ? Hãy thử nó trong thực tế:
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;
}
Nếu chúng ta in ra kết quả của phương pháp System.out.println(getPlanetAtmosphere(3))thì hành tinh quê hương của chúng ta sẽ không phù hợp cho sự sống. Hay phù hợp? Hãy tự đánh giá: [Carbon dioxide, Nitrogen, Oxygen, Hydrogen, Helium, Metan, Hydrogen, Helium], Tại sao điều này lại xảy ra? Chương trình thực hiện tất cả các trường hợp sau lần so khớp đầu tiên và cho đến hết khối switch.

Nghỉ tối ưu hóa quá mức

Lưu ý rằng chúng ta có thể cải thiện phương pháp này bằng cách sắp xếp các lệnh ngắt và các tùy chọn lựa chọn khác nhau
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;
}
Có vẻ ngắn hơn phải không? Chúng tôi đã giảm tổng số câu lệnh bằng cách sắp xếp thứ tự các trường hợp và nhóm lại. Bây giờ mỗi loại khí được thêm vào danh sách chỉ bằng một dòng mã. Việc liệt kê ví dụ cuối cùng của phương pháp này chỉ được đưa ra để minh họa cho công việc; không nên viết theo phong cách như vậy. Nếu tác giả (và thậm chí hơn thế nữa là các lập trình viên bên thứ ba) của mã tương tự phải duy trì nó, thì sẽ rất khó khôi phục logic cho việc hình thành các khối lựa chọn và mã thực thi cho câu lệnh java switch.

Sự khác biệt từ nếu

Mặc dù các câu lệnh ifswitch có hình thức tương tự nhau , nhưng đừng quên rằng toán tử trắc nghiệm switch căn cứ vào việc lựa chọn các tùy chọn thực thi dựa trên một GIÁ TRỊ CỤ THỂ, còn trong if. có thể là bất kỳ biểu thức logic nào. Hãy tính đến thực tế này khi thiết kế mã của bạn. Chúng ta hãy xem xét kỹ hơn những cải tiến dành cho switch trong các phiên bản Java khác nhau.

Chuyển sang Java 7

Trước Java 7, các nguyên hàm byte, short, char và int có thể được sử dụng làm giá trị cho một switch. Ngoài ra còn có hỗ trợ cho enum và trình bao bọc của các kiểu nguyên thủy được liệt kê ở trên: Ký tự, Byte, Ngắn và Số nguyên. Nhưng thường thì chúng ta cần tìm giá trị của chuỗi chuyển đổi java! Đây là giao diện của 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 !");
Và liệt kê:
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;
  }
}
Nhưng bắt đầu từ Java 7, có thể sử dụng kiểu String làm giá trị cho switch:
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 !");
}
Mặc dù có các tính năng mới, cách tiếp cận sử dụng enum linh hoạt hơn và được khuyến khích sử dụng: chúng ta có thể sử dụng lại enum này nhiều lần.

Chuyển sang Java 12

Java 12 đã cải tiến biểu thức Switch để khớp mẫu. Nếu chúng ta sử dụng Switch như trong ví dụ trên, để đặt giá trị của một số biến, chúng ta phải tính giá trị và gán nó cho biến đã cho, sau đó sử dụng break:
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;
}
Nhưng nhờ khả năng của Java 12, chúng ta có thể viết lại biểu thức này như sau:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
Chúng ta hãy xem xét những thay đổi một chút:
  1. Nếu trước đây chúng ta đặt một giá trị biến bên trong các khối trường hợp, vì bản thân câu lệnh switch không thể trả về bất kỳ thứ gì, thì bây giờ chúng ta có cơ hội như vậy và chúng ta trực tiếp trả về giá trị đó bằng cách sử dụng switch.

  2. Trước đây, chúng ta không thể có bất cứ điều gì ở bên phải break nữa, nhưng bây giờ chúng ta sử dụng nó như một câu lệnh return để trả về giá trị của switch. Dấu hai chấm đánh dấu điểm vào khối câu lệnh. Nghĩa là, từ thời điểm đó, việc thực thi tất cả mã bên dưới bắt đầu, ngay cả khi gặp phải một nhãn khác.

    Kết quả là một quá trình chuyển đổi từ điểm này sang điểm khác, còn được gọi là sự chuyển tiếp từ đầu đến cuối .

Câu lệnh switch trong Java - 2Để hoàn thành việc vượt qua như vậy, bạn phải xem qua tất cả các phần tử một cách đầy đủ hoặc sử dụng break hoặc return. Sự đổi mới trong java 12 mang lại cho chúng ta khả năng sử dụng toán tử lambda, từ đó đảm bảo rằng chỉ mã ở bên phải của nó mới được thực thi. Không có bất kỳ "thất bại" nào. Ví dụ trước sẽ trông như thế nào trong trường hợp này:
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
Code đã trở nên đơn giản hơn rất nhiều phải không? Và một điều nữa: toán tử lambda cũng có thể đóng vai trò như một dạng tương tự điển hình của dấu hai chấm, sau đó có cả một khối với một số thao tác:
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;
  }
};
Chà, điều gì sẽ xảy ra nếu trong một số trường hợp, giá trị trả về giống nhau? Hóa ra là chúng ta thực sự có những trường hợp giống nhau cho một số giá trị khác nhau. Đây là cách có thể rút ngắn điều này bằng cách sử dụng các tính năng mới trong Java 12:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Chuyển sang Java 13

Trong Java 13, cách switch trả về một giá trị đã thay đổi. Nếu trong java 12, chúng ta đã viết giá trị trả về sau break, giá trị này đóng vai trò là giá trị trả về cho khối switch, thì bây giờ chúng ta sẽ trả về giá trị bằng cách sử dụng từ năng suất . Hãy xem:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
Đồng thời, mã viết bằng java 12 sử dụng break để trả về sẽ không được biên dịch (( Câu lệnh switch trong Java - 3Break sẽ được sử dụng, nhưng trong trường hợp chúng ta không cần trả về bất cứ thứ gì.

Tổng cộng

  • Sử dụng câu lệnh tình huống khi có nhiều hơn hai nhánh để tránh làm lộn xộn mã của bạn với các cấu trúc if.
  • Đừng quên kết thúc khối logic của từng nhánh tương ứng với một giá trị cụ thể (khối trường hợp) bằng lệnh gọi break .
  • Ngoài một số kiểu nguyên thủy, câu lệnh switch còn có thể sử dụng kiểu EnumString làm biểu thức .
  • Hãy nhớ khối mặc định - sử dụng nó để xử lý các giá trị lựa chọn ngoài kế hoạch.
  • Để tối ưu hóa hiệu suất, hãy di chuyển các nhánh mã có các lựa chọn phổ biến nhất về đầu khối chuyển đổi.
  • Đừng quá bận tâm đến việc "tối ưu hóa" bằng cách loại bỏ dấu ngắt ở cuối khối chọn trường hợp - mã như vậy rất khó hiểu và do đó, khó duy trì trong quá trình phát triển.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION