2015-06-14 28 views
19

Cách biên dịch này không có lỗi? Theo hiểu biết của tôi, trình biên dịch kiểm tra kiểu biến (trong trường hợp này là String), sau đó xem liệu loại biểu thức ở phía bên phải có tương ứng với kiểu của biến hay ít nhất một kiểu con nhưng hãy dính vào trường hợp đơn giản lớp String kể từ lần cuối cùng).Tại sao khởi tạo biến cho một biểu thức gán [Chuỗi x = (x = y)] biên dịch?

public class InitClass { 
    public static void main(String[] args) { 
    String str = (str = "hello"); 
    System.out.println(str); 
    } 
} 

Câu hỏi của tôi là cách str = "hello" biên dịch? Trình biên dịch có biết rằng str phải thuộc loại String?

+0

(str = "hello") trả về chuỗi "hello". Eclipse không khuyến khích nó với thông điệp: "Việc gán cho biến str không có hiệu lực" – LeTex

+3

@LeTex Tôi thường đặt Eclipse chặt chẽ hơn và báo cáo chúng dưới dạng lỗi hơn là cảnh báo. Tôi không thấy lý do gì để bất cứ ai sử dụng các cấu trúc như thế này mặc dù chúng được JLS cho phép. – biziclop

+2

Một trong những câu hỏi thú vị mà bạn đang suy nghĩ "ai đang viết mã như thế này và tại sao". Hoàn toàn học tập, chắc chắn? – TEK

Trả lời

15

Khi đánh giá một assignment expression

Thứ nhất, các toán hạng bên trái được đánh giá để tạo ra một biến. Nếu đánh giá này hoàn thành đột ngột, sau đó biểu thức chuyển nhượng hoàn thành đột ngột vì cùng một lý do; toán hạng bên phải không phải là được đánh giá và không có chuyển nhượng nào xảy ra.

Điều đó tạo ra biến số str. Sau đó,

Nếu không, toán hạng bên phải được đánh giá. Nếu đánh giá này hoàn thành đột ngột, sau đó biểu thức chuyển nhượng hoàn thành một cách đột ngột vì lý do tương tự và không có chuyển nhượng nào xảy ra.

Trong ví dụ của bạn, toán hạng tay phải là một biểu thức gán khác. Vì vậy, str, toán hạng tay phải của toán tử gán, được đánh giá lại để tạo ra một biến, str. Sau đó

Nếu không, giá trị của toán hạng bên phải được chuyển đổi sang các loại của biến bên trái, là đối tượng của giá trị thiết lập chuyển đổi (§5.1.13) để thiết lập giá trị tiêu chuẩn thích hợp (không phải là giá trị số mũ mở rộng), và kết quả của chuyển đổi là được lưu trữ trong biến.

Vì vậy, "hello" được lưu trữ vào str. And since

Khi chạy, kết quả của biểu thức gán là giá trị của biến sau khi chuyển nhượng đã xảy ra. Kết quả của biểu thức gán không phải là một biến.

kết quả của sự phân công của "hello"-str là giá trị "hello", giá trị được lưu trữ trong một lần nữa str.

0

Điều đầu tiên xảy ra là trình biên dịch xác định loại tham chiếu sau đó biết rằng đó là một chuỗi gán "hello" cho str là hợp lệ.

5

trường hợp của bạn là tương đương với

String str; 
str = (str = "hello"); 

Mặc dù nhiệm vụ là buồn cười, không có gì sai khái niệm là.

Tuy nhiên, việc khởi tạo biến tham chiếu chính nó rõ ràng không phải là một ý tưởng hay. Trình biên dịch sẽ cố gắng gắn cờ nó trong các tình huống rất có thể là lỗi lập trình; trình biên dịch không làm như vậy một số lần; và cũng có thể đi quá nhiều lần khác.

Biến cục bộ có yêu cầu khắt khe hơn (biến trường) - nó phải được gán trước trước khi giá trị của nó được sử dụng. Ví dụ, điều này sẽ không biên dịch, vì var cục bộ được đọc trước khi nó được gán.

String str; // local variable 
str = str; // error, try to read `str` before it's assigned 

Biến trường luôn có giá trị ban đầu mặc định; tuy nhiên, việc kiểm tra trình biên dịch cho những sai lầm programer rõ ràng

int x = x+1; // error. x is field variable. 

Nhưng nó không phải là thảm họa nếu việc kiểm tra như vậy thất bại, kể từ x có một giá trị 0 trước khi phân công rõ ràng

int x; 
{ x=x+1; } // ok. x==0, then x==1 after assignment 

Tuy nhiên, nếu xfinal, mã ở trên không thành công, vì trình biên dịch yêu cầu gán rõ ràng x trước khi đọc x, cùng yêu cầu cho một biến cục bộ. Nhưng việc kiểm tra này có thể được phá vỡ, bởi vì nó không thể phân tích và ngăn chặn nó đầy đủ cho các biến lĩnh vực

final int x = (this).x+1; // compiles! 

Trong một số trường hợp, trình biên dịch đi xuống biển, ngăn chặn các trường hợp sử dụng hợp pháp liên quan đến lambda

Runnable r1 =()->System.out.println(r1); // r1 is a field variable 

Không có gì khái niệm có vấn đề trong trường hợp sử dụng này; nó có thể bị phá vỡ bởi (this)..

+1

Phần cuối cùng của câu trả lời của bạn rất thú vị, +1 – user2336315

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