2009-03-17 28 views
14

Với mã sau, ixAdd sẽ làm những gì bạn mong đợi, i. e. trả về giá trị của ix trước khi tăng, nhưng tăng thành viên lớp trước khi rời khỏi hàm?Trong Java, toán tử tăng bài viết hoạt động như thế nào trong câu lệnh trả về?

class myCounter { 
    private int _ix = 1; 

    public int ixAdd() 
    { 
     return _ix++; 
    } 
} 

Tôi đã không hoàn toàn chắc chắn nếu các quy tắc thông thường cho bài/increment trước cũng sẽ được áp dụng trong báo cáo lợi nhuận, khi chương trình rời khỏi stack frame (hoặc bất cứ điều gì trong Java) của hàm.

+1

Tại sao bạn không thử? –

+2

ehm .. bạn có nghĩa là, giống như dán mã ở trên trong trình soạn thảo của tôi và chạy nó? Tôi không biết, xin lỗi. :-p Tôi sẽ tự mình uống một tách cà phê ... –

+0

bình chọn cho việc đóng ... Tôi nghĩ tác giả có thể đóng nó ngay lập tức? –

Trả lời

25

Phần quan trọng là tăng/giảm bài đăng xảy ra ngay lập tức sau khi biểu thức được đánh giá. Nó không chỉ xảy ra trước khi sự trở lại xảy ra - nó xảy ra trước khi bất kỳ biểu thức sau nào được đánh giá. Ví dụ, giả sử bạn đã viết:

class myCounter { 
    private int _ix = 1; 

    public int ixAdd() 
    { 
     return _ix++ + giveMeZero(); 
    } 

    public int giveMeZero() 
    { 
     System.out.println(_ix); 
     return 0; 
    } 
} 

Điều đó sẽ in ra kết quả tăng lên là tốt, vì thặng dư xảy ra trước khi giveMeZero() được gọi.

+0

Cảm ơn câu trả lời, Jon. Như Paul Tomblin đã chỉ ra, gõ mã trong trình soạn thảo của tôi thay vì bài viết cũng sẽ trả lời nó. Nhưng bây giờ tôi nhận được nhiều hơn từ nó hơn tôi yêu cầu. –

+0

@Jon: Đối với những người đến từ C đến Java (sẽ có rất nhiều người), đây là một điều tốt để chỉ ra. Là một người dùng Java thời gian dài, người đầu tiên sử dụng C trong một thời gian dài, tôi không biết rằng Java đã định nghĩa cách ++ hoạt động rõ ràng hơn nhiều so với C. Tôi đã học cách tránh "thông minh" ++ sử dụng từ C! – Eddie

+0

_Không chỉ nó xảy ra trước khi sự trở lại xảy ra_ nhưng câu lệnh return không trả lại giá trị gia tăng nếu biến cục bộ của nó. Ví dụ của bạn cho thấy một biến toàn cầu. – ernesto

1

Có, các quy tắc thông thường áp dụng cho tăng bài đăng ngay cả trên bảng sao kê trả lại. Về cơ bản, những gì nó sẽ làm ở mức thấp là lưu trữ giá trị trả về vào thanh ghi, sau đó tăng thành viên lớp, sau đó trở về từ phương thức.

Bạn có thể thấy điều này trong a later answer cho câu hỏi này cho thấy mã byte.

0

Vâng, đúng vậy.

Nhưng đừng làm điều đó, đó là phong cách xấu có tác dụng phụ trong biểu thức.

+0

Tác dụng phụ ở đây là rất nhiều dự định và tôi không thể thấy nó có hại gì. –

+0

Nhưng nó khó hiểu, như câu hỏi của bạn cho thấy. – starblue

16

Vâng, chúng ta hãy nhìn vào bytecode (sử dụng javap -c <classname> để xem nó cho mình):

Compiled from "PostIncTest.java" 
class myCounter extends java.lang.Object{ 
myCounter(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: aload_0 
    5: iconst_1 
    6: putfield #2; //Field _ix:I 
    9: return 

public int ixAdd(); 
    Code: 
    0: aload_0 
    1: dup 
    2: getfield #2; //Field _ix:I 
    5: dup_x1 
    6: iconst_1 
    7: iadd 
    8: putfield #2; //Field _ix:I 
    11: ireturn 

} 

Như bạn thấy, hướng dẫn 6 và 7 trong ixAdd() xử lý thặng dư trước khi trở lại. Do đó, như chúng ta mong đợi, toán tử giảm đi thực sự có tác dụng khi được sử dụng trong một câu lệnh trả về. Tuy nhiên, lưu ý rằng có một lệnh dup trước khi hai lệnh này xuất hiện; giá trị gia tăng là (tất nhiên) không được phản ánh trong giá trị trả về.

0

Trả về giá trị trước số gia tăng và sau đó tăng _ix. Vì vậy, lần đầu tiên bạn gọi phương thức ixAdd trên một cá thể của myCounter nó sẽ trả về 1, lần thứ hai nó sẽ trả về 2, và cứ thế.

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