2015-11-11 23 views
7

Tôi đã làm việc trên trường hợp chuyển đổi.java 8: sự khác biệt giữa class.getName() và String literal

Nếu chúng ta sử dụng class.getName(), sau đó, tôi nhận được lỗi "trường hợp biểu thức phải là biểu thức hằng số" như sau:

switch(param.getClass().getName()) 
    { 
     case String.class.getName(): 
      // to do 
      break; 
    } 

Thậm chí nếu chúng ta sau, lấy chuỗi tên lớp trong một liên tục, sau đó cũng nhận được cùng một lỗi:

public static final String PARAM_NAME = String.class.getName(); 
switch(param.getClass().getName()) 
    { 
     case PARAM_NAME: 
      // to do 
      break; 
    } 

Nhưng, nếu tôi sau đó, sử dụng các chuỗi chữ "java.lang.String", không có lỗi:

public static final String PARAM_NAME = "java.lang.String"; 

Ai có thể giải thích điều này, tại sao nó không lấy hai trường hợp đầu tiên và lấy cái cuối cùng? Cảm ơn trước.

Trả lời

8

classObject.getName() là cuộc gọi phương thức và kết quả của cuộc gọi phương thức theo định nghĩa không phải hằng số biên dịch. Một chuỗi ký tự hằng số biên dịch.

Lưu ý rằng trong khi nhiều trường hợp có thể lấy tham chiếu static final làm hằng số trong suốt thời gian của chương trình, thì switch phải có các tùy chọn được mã hóa cứng tại thời điểm biên dịch. Giá trị của một mục tiêu case phải là giá trị enum hoặc một (thời gian biên dịch) ConstantExpression.

+0

Nhưng, tôi đang dùng nó trong biến 'tĩnh cuối cùng' (tức là, hằng số), sau đó, cũng không dùng nó? –

+0

trình biên dịch thực hiện một số phép thuật và tôi giả định hai điều đầu tiên được biên dịch vào cùng một mã byte. Cuối cùng bạn đưa ra, có String literal được sử dụng và do đó nó hoạt động –

+2

@KrishnaKumar Một trường 'final final' không nhất thiết phải là một hằng số biên dịch, ngay cả khi cho mục đích thực tế, nó là một hằng số khi chạy. – chrylis

6

Mỗi nhãn trường hợp phải là "biểu thức liên tục". "Biểu hiện liên tục" được định nghĩa trong ngôn ngữ Java Standard, §15.28 Constant Expressions là gì:

A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

  • Literals of primitive type and literals of type String

...

  • Simple names that refer to constant variables

Không có phương pháp các cuộc gọi được liệt kê ở đó, vì vậy kết quả gọi phương thức không thể là biểu hiện liên tục ngay cả khi phương pháp này là tầm thường. Nhưng "Các tên đơn giản tham chiếu đến các biến không đổi" được liệt kê ở đây, do đó tham chiếu đến biến cố định cũng là một hằng số.

4

Lý do điều này không hoạt động là giá trị của case để bật cần được biết tại thời điểm biên dịch (vì mã này được mã hóa cứng và được gạch chéo trong bytecode).

String.class.getName() là cuộc gọi phương thức được đánh giá khi chạy. Có, static final đảm bảo rằng nó không thay đổi sau khi lớp được tải ban đầu. Nhưng tất cả những điều đó kéo dài sau thời gian biên dịch.

Trình biên dịch không bao giờ gọi bất kỳ mã nào từ mã nguồn ứng dụng (ngoại trừ trường hợp có thể xử lý chú thích). Nó chỉ biên dịch nó.

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