2011-06-21 27 views
8

Tôi không phải là người mới đối với java và C#. Tôi nghĩ tôi hiểu khái niệm về phạm vi biến cho đến gần đây tôi đã hỏi câu hỏi này trong một cuộc phỏng vấn:Một câu hỏi khó về Java đơn giản: phạm vi biến

public class Q{ //starting y scope 

    static int x = 11; 
    private int y = 33; // Just added a “private” modifier to make it clearer. 

    public static void main(String args[]){ 
     Q q = new Q(); 
     q.call(5); 
    } 

    public void call(int x){ 
     Q q = new Q(); 

     this.x = 22; 
     y = 44; 

     System.out.println("Output: " + Q.x); 
     System.out.println("Output: " + q.x); 
     System.out.println("Output: " + q.y); 
    } 

} //ending y scope 

Xác định đầu ra của chương trình này.

Tôi đã trả lời câu hỏi trong cuộc phỏng vấn rằng đầu ra sẽ là ngoại lệ thời gian chạy. Theo sự hiểu biết của tôi, y được khai báo là private, và phương thức instance call() đang cố gắng truy cập cá thể biến private cá thể của một cá thể khác của lớp Q. Làm thế nào điều đó có thể xảy ra? Tuy nhiên, trả lời câu hỏi này sai đã không ảnh hưởng đến cuộc phỏng vấn của tôi quá nhiều vì đây là loại câu hỏi "cơ bản phức tạp". Nhưng, trả lời sai có nghĩa là kinh nghiệm Java của năm tôi cần được phục hồi, điều đó thật khủng khiếp!

Ai đó có thể giúp tôi về vấn đề này không? Tôi sẽ được rất nhiều đánh giá cao!

+0

Sản lượng có 11,22,33 không? –

+4

Không hoàn toàn chắc chắn làm thế nào đây là một câu hỏi "khó khăn". – R0MANARMY

+9

Tôi có thể nói 22, 22, 33, 'x' là tĩnh, vậy tại sao nó không thể được thay đổi bởi' this.x = 22'? – Kevin

Trả lời

24

Bạn có thể truy cập private thành viên trong lớp học của riêng mình, thậm chí từ một phiên bản khác của lớp học.

+1

Mind = * Blown * ... –

+1

+1 nếu bạn không thể thì sẽ không thể thực hiện 'So sánh' được. – Qwerky

+1

@Qwerky: Bạn giả sử mọi người mã đúng biến là riêng tư :) –

8

private chỉ có nghĩa là không thể truy cập được bởi các đối tượng của một lớp khác, không phải bất kỳ đối tượng nào khác. Vì vậy, một đối tượng Q có thể truy cập các thành viên riêng của đối tượng khác Q.

[Lưu ý rằng nếu điều này là bất hợp pháp, điều này sẽ kích hoạt lỗi trình biên dịch, không phải ngoại lệ thời gian chạy.]

6

Biến riêng tư có thể truy cập được trong văn bản chương trình của lớp khai báo. Nó không quan trọng nếu một cá thể cố gắng truy cập các biến trong một cá thể khác, miễn là mã nằm trong cùng một lớp.

Từ JLS section 6.6:

Ngược lại, nếu các thành viên hoặc constructor được khai báo là private, sau đó truy cập được phép khi và chỉ khi nó xảy ra trong cơ thể của lớp cấp cao nhất (§7.6) mà có chứa tuyên bố của thành viên hoặc nhà xây dựng.

+0

Cảm ơn !! Liên kết bạn chia sẻ thực sự giúp ích cho – lixiang

3

private có nghĩa là các lớp bên ngoài lớp này không thể thấy biến. Trong định nghĩa lớp này, tất cả các phương thức và biến có thể được truy cập.

3

Hạn chế quyền truy cập phải được thực thi thời gian biên dịch không phải trong thời gian chạy, do đó trình biên dịch sẽ ngăn biên dịch mã nếu nó sai.

Nhưng trình sửa đổi truy cập được áp dụng ở cấp lớp, vì vậy bạn luôn có thể truy cập thành viên riêng tư từ chính lớp đó.

Khi bạn sao chép một đối tượng, điều này thường hữu ích vì bạn chỉ có thể đặt một loạt giá trị trong bản sao trực tiếp, điều này có thể khó truy cập nếu không. Ngoài ra khi so sánh các đối tượng với một phương thức Equals, nó có thể khá tiện dụng vì nó là lớp không phải là cá thể xác định các hạn chế truy cập.

+0

Tuyệt vời !! Tôi đã học được rất nhiều điều tôi nghĩ :) – lixiang

2

Tôi nghĩ rằng sẽ có một vấn đề biên dịch vì thuộc tính static int x = 11 được khai báo tĩnh và trong phương thức call, biến x được truy cập bởi this.Bạn không thể tạo this thành biến tĩnh trong lớp.

Không có vấn đề với thành viên riêng y.

+3

"Bạn không thể biến nó thành một biến tĩnh trong một lớp." Tại sao không??? Bạn có thể sử dụng từ khóa "này" để truy cập bất kỳ biến hoặc phương thức nào bên trong một lớp, bất kể nó có bộ điều biến nào. –

+0

Như Filipe đã nói, điều đó là có thể. Tuy nhiên, nó không được khuyến khích và sẽ mang lại một cảnh báo trình biên dịch. –

+0

Vâng, tôi đã đọc lại thông số kỹ thuật và thử một số thử nghiệm. Tôi đã sai. – Dimitri

3

Như đã được chỉ ra, các thành viên riêng tư của các phiên bản khác có thể truy cập được từ lớp học. Ngoài ra, bạn đã không chính xác về ngoại lệ thời gian chạy: sẽ không có ngoại lệ thời gian chạy ngay cả khi bạn sửa đổi mã để bạn cố truy cập thành viên riêng của một lớp khác, mã sẽ không biên dịch được.

2

Câu trả lời "phỏng vấn" chính xác là bất kỳ ai đã viết mã như thế này sẽ bị sa thải! Tên lớp Lousy, bình luận vô dụng về phạm vi y; sử dụng không chuẩn của "this" mà thực sự chỉ nên được sử dụng cho các biến mẫu, không phải biến lớp; tái sử dụng 'q' trong các phương thức chính và gọi.

Nó nhắc tôi về các cuộc thi C++ bị làm phiền, chính xác loại Java vô nghĩa được thiết kế để tránh.

Tệ hơn điều này, tuy nhiên, rất khó để nói từ các nhận xét và câu trả lời đầu ra của chương trình là gì. Tôi có đi theo '6' trên bình luận của Kevin không?

Tôi muốn một quản trị viên sẽ refactor tất cả điều này. Và tôi sẽ nói với một người phỏng vấn (nếu đây thực sự là một câu hỏi phỏng vấn, mà tôi nghi ngờ) rằng chúng ta nên chạy mã, nhận câu trả lời, và sau đó tạo một bài kiểm tra đơn giản để xác nhận rằng câu trả lời không thay đổi khi chúng ta tái cấu trúc mã để phù hợp với việc sử dụng tiêu chuẩn.

+0

Điểm của câu hỏi phỏng vấn là: bạn biết rõ java sẽ làm gì trước khi bạn chạy nó? Việc viết mã hoạt động nhanh hơn và rẻ hơn khi bạn không cần phải gọi trong "quản trị" để cung cấp cho bạn câu trả lời.Nếu câu trả lời của bạn trong một cuộc phỏng vấn được gọi trong "quản trị" thì câu hỏi tiếp theo của tôi là "tại sao tôi phải trả tiền cho bạn thay vì chỉ trả tiền cho quản trị viên?" – mwengler

+0

Đây thực sự là một câu hỏi phỏng vấn, họ đã cố tình làm cho lớp này trông như thế. Sau gần một năm khi tôi nhìn lại câu hỏi này một lần nữa (nhờ bạn Ed cho bình luận bây giờ) Tôi nhận ra rằng câu hỏi này không có ý nghĩa nhiều như năm cuối cùng là một lập trình viên thực sự, tôi gần như chưa bao giờ sử dụng Java cách này. Nhưng có @mwengler, điểm của câu hỏi là chỉ cần thử nghiệm như thế nào bạn biết java và rõ ràng là tôi không biết java mà cũng một năm trước đây: p – lixiang