2013-04-05 27 views
10

Trong khi nghiên cứu another question, tôi rất ngạc nhiên khi phát hiện ra rằng các mã Java sau biên dịch không có lỗi:Sử dụng this.var trong quá trình khởi var của

public class Clazz { 
    int var = this.var + 1; 
} 

Trong JDK6 tôi, var được khởi tạo 1.

Mã trên có ngữ nghĩa được xác định rõ ràng hay hành vi của nó không xác định? Nếu bạn nói nó được xác định rõ, vui lòng trích dẫn các phần có liên quan của JLS.

+0

Có gì sai ở đây? –

+0

@Sudhanshu: 'var' đang được sử dụng để khởi tạo' var'. – NPE

+0

Đầu tiên, this.var = 0, sau đó bạn thêm nó 1, sau đó nó sẽ trở thành 1 –

Trả lời

4

Được đề cập trong ví dụ 8.3.2.3-1 trong section 8.3.2.3. Trong văn bản để ví dụ

class Z { 
    static int peek() { return j; } 
    static int i = peek(); 
    static int j = 1; 
} 
class Test { 
    public static void main(String[] args) { 
     System.out.println(Z.i); 
    } 
} 

chú thích nói:

... initializer biến cho tôi sử dụng phương pháp lớp ú để truy cập giá trị của k biến trước j đã được khởi tạo bởi bộ khởi tạo biến của nó, tại thời điểm đó nó vẫn có giá trị mặc định của nó (§4.12.5).

Điều này sẽ ánh xạ trực tiếp đến tình huống của bạn.

+0

Brilliant, đây là nó, cảm ơn. – NPE

0

Introduction of Chapter 16

Chương 16 mô tả cách chính xác, trong đó ngôn ngữ đảm bảo rằng các biến địa phương chắc chắn thiết lập trước khi sử dụng. Trong khi tất cả các biến số khác được tự động khởi tạo thành giá trị mặc định, ngôn ngữ lập trình Java không tự động khởi tạo biến cục bộ để tránh che lỗi lập trình.

3

Chapter 8.3.2.2. paragraph 2:

biểu thức khởi tạo cho các biến dụ được phép tham khảo các đối tượng hiện nay (§15.8.3) và sử dụng các siêu từ khóa (§15.11.2, §15.12).

Mặc dù đoạn tiếp theo cho biết thêm:

Sử dụng các biến Ví dụ có tờ khai xuất hiện textually sau khi sử dụng đôi khi bị hạn chế, mặc dù các biến dụ là trong phạm vi. Xem §8.3.2.3 để biết các quy tắc chính xác điều chỉnh tham chiếu tới các biến mẫu.

-1

Không có gì sai trong trường hợp này. từ khóa này đề cập đến đối tượng hiện tại và nó được sử dụng để phân biệt biến cục bộ và biến mẫu. Giá trị của biến địa phương có thể được gán vào biến dụ tương tự như vậy, câu ngược lại cũng có thể. Điều đó có nghĩa là chúng ta có thể gán giá trị của biến instance thành một biến cục bộ.

tham khảo chương 4.12.3 Các loại biến từ http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf (trang 80). Ví dụ này cũng được đưa ra ở đây.

 **Example 4.12.3-1. Different Kinds of Variables** 
     class Point { 
     static int numPoints; // numPoints is a class variable 
     int x, y; // x and y are instance variables 
     int[] w = new int[10]; // w[0] is an array component 
     int setX(int x) { // x is a method parameter 
     int oldx = this.x; // oldx is a local variable 
     this.x = x; 
     return oldx; 
     } 
    } 
+1

Câu hỏi OP khác nhau. Câu hỏi liên quan đến 'các tham chiếu chuyển tiếp'. Câu hỏi OP không nói về biến cục bộ và biến mẫu. – AmitG

0

Sử dụng đơn giản tên không được phép trong trường hợp forward references theo JSL. Vì vậy, phải sử dụng này từ khóa để truy cập các biến như vậy.

class UseBeforeDeclaration { 
    int h = j++; // error - `j` read before declaration 
    int l = this.j * 3; // ok - not accessed via simple name 
    int j; 
} 
+1

Điều đó đã được xác định trong câu hỏi được liên kết ở đầu câu hỏi này. NPE đang hỏi là gì: chúng ta có đảm bảo rằng 'var' sẽ là một sau' int var = this.var + 1; 'và tại sao? – assylias

0

Vì tất cả các biến không phải cục bộ được gán giá trị ban đầu (và chuyển nhượng xảy ra trước mọi thứ khác), không có vấn đề gì khi đọc chúng bất cứ lúc nào.

Thông số kỹ thuật có chọn lọc cấm truy cập một số ở một số trường hợp, lý do rằng những lần truy cập đó rất có thể là lỗi lập trình. Nhưng có những truy cập được cho phép, họ sẽ có ngữ nghĩa được xác định rõ.

Thực ra, một lập trình viên có thể dễ dàng bỏ qua các hạn chế và truy cập gián tiếp vào trường này; ngữ nghĩa của truy cập đó giống như truy cập "trực tiếp" nếu nó được cho phép.

int var = this.var + 1;  // suppose javac forbids this 

int var = this.getVar() + 1; // but can javac forbid this? 
Các vấn đề liên quan