2015-04-18 16 views
11

Vì Java 1.7, các chuỗi có thể được sử dụng với các câu lệnh chuyển đổi, điều này khiến tôi băn khoăn về điều gì đó. Các câu lệnh switch trên các giá trị số nguyên được chuyển thành các bảng nhảy, nhanh hơn chỉ đơn giản là thực hiện kiểm tra số if trên các số nguyên được tính khi chạy; một tối ưu hóa tương tự có thể được thực hiện với chuỗi hoặc là điều này chỉ cú pháp đường?Có phải chuyển đổi với chuỗi không chỉ là cú pháp cú pháp?

+0

'chuỗi' tắc dường như được thực hiện bằng cách sử dụng bản đồ kích thước cố định dẫn đến hiệu suất logarit cho số nhỏ mặt hàng. Xem http://java-performance.info/string-switch-performance/ – isnot2bad

Trả lời

4

Có chuyển đổi bằng chuỗi là đường cú pháp. Từ here

1) Chuỗi trong chuyển đổi là đường cú pháp, không thay đổi mức JVM.

2) Bên trong nó sử dụng bằng phương pháp so sánh, có nghĩa là, nếu bạn vượt qua null nó sẽ ném java.lang.NullPointerException, vì vậy hãy cẩn thận của đó.

3) Các chuỗi trong báo cáo chuyển đổi phân biệt chữ hoa chữ thường, chỉ thích sử dụng một trường hợp và chuyển đổi đầu vào sang trường hợp ưu tiên trước khi chuyển sang câu lệnh chuyển đổi .

Ngoài ra kiểm tra How String in Switch works in Java 7

Từ liên kết tương tự nếu bạn thấy ví dụ:

public class StringInSwitchCase{ 
    public static void main(String[] args) { 
     String mode = args[0]; switch (mode) { 
      case "ACTIVE": System.out.println("Application is running on Active mode"); 
       break; 
      case "PASSIVE": System.out.println("Application is running on Passive mode"); 
       break; 
      case "SAFE": System.out.println("Application is running on Safe mode"); 
     } } } 

và Bộ luật decompiled:

import java.io.PrintStream; 
public class StringInSwitchCase{ 
    public StringInSwitchCase() { } 
    public static void main(string args[]) { 
     String mode = args[0]; String s; 
     switch ((s = mode).hashCode()) { 
      default: break; 
      case -74056953: if (s.equals("PASSIVE")) { 
       System.out.println("Application is running on Passive mode"); } 
       break; 
      case 2537357: if (s.equals("SAFE")) { System.out.println("Application is running on Safe mode"); } 
       break; 
      case 1925346054: if (s.equals("ACTIVE")) { System.out.println("Application is running on Active mode"); } 
       break; } } } 

bạn sẽ tìm ra rằng chuỗi trong Chuyển đổi hoạt động bằng cách sử dụng hashCode()equals().

Đúng như dự đoán nó sử dụng phương thức hashCode() để chuyển đổi và bằng() phương pháp để xác minh, Điều này có nghĩa nó chỉ là một đường cú pháp, chứ không phải là một chức năng có nguồn gốc sẵn có.

+1

Hai câu lệnh cuối cùng trong đó đánh tôi như mâu thuẫn: là sự khác biệt về hiệu quả mã byte thực sự lớn nếu nó yêu cầu bạn tạo mới, thấp hơn/chuỗi chữ hoa để sử dụng nó? –

+4

Vì vậy ... nếu mã byte hiệu quả hơn, thì chúng không chính xác là cú pháp. – RealSkeptic

+0

@JeroenVannevel: - Có điều đó mâu thuẫn. Tôi đã xóa phần đó và thêm mã để làm cho nó rõ ràng hơn. –

7

Trình biên dịch tối ưu hóa một tuyên bố switch dựa trên các giá trị chuỗi bằng cách sử dụng phương pháp hashCode(), và sau đó sử dụng một bảng tra cứu trong bytecode. Điều này thường hiệu quả hơn tuyên bố if - else.

Ví dụ, sau đây:

String string = "x"; 
switch(string) { 
    case "x": System.out.println("x"); 
       break; 
    case "y": System.out.println("y"); 
       break; 
    case "z": System.out.println("z"); 
       break; 
} 

được chuyển thành bytecode này:

ldc "x" 
astore_1 
aload_1 
astore_2 
iconst_m1 
istore_3 
aload_2 
invokevirtual java/lang/String/hashCode()I 
tableswitch 120 
    10 
    17 
    24 
    default: 30 
aload_2 
ldc "x" 
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z 
ifeq 30 
iconst_0 
istore_3 
goto 30 
aload_2 
ldc "y" 
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z 
ifeq 30 
iconst_1 
istore_3 
goto 30 
aload_2 
ldc "z" 
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z 
ifeq 30 
iconst_2 
istore_3 
iload_3 
tableswitch 0 
    32 
    36 
    40 
    default: 43 
getstatic java/lang/System/out Ljava/io/PrintStream; 
ldc "x" 
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 
goto 43 
getstatic java/lang/System/out Ljava/io/PrintStream; 
ldc "y" 
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 
goto 43 
getstatic java/lang/System/out Ljava/io/PrintStream; 
ldc "z" 
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V 
return 
+1

Tại sao điều này lại hiệu quả hơn? Một chuyển đổi về các phím cơ bản ngẫu nhiên không thể sử dụng một bảng nhảy. Bảng nhảy sẽ cần 2^32 mục trong trường hợp xấu nhất. – usr

+1

@usr Ngay cả khi một bảng nhảy không thể được sử dụng, ngay cả khi công tắc kết thúc một loạt các kiểm tra if-else trên một giá trị số nguyên, thì vẫn rẻ hơn một loạt các kiểm tra if-else trên một giá trị chuỗi. – hvd

Các vấn đề liên quan