2012-02-26 76 views
16

Trước tiên, xin lỗi nếu đây là một câu hỏi rất cơ bản và tôi quảng bá rằng tôi vẫn là một con khỉ mã. Tôi được hỏi trong một cuộc phỏng vấn để làm sáng tỏ System.out.println(); tôi đã giải thích theo cách sautrong System.out.println()

//this class belongs to java.lang package 
class System{ 
    public static PrintStream out; 
} 
//this class belongs to java.io package 
class PrintStream{ 
public void println.. 
} 

Tôi đã giải thích rằng System.out là hợp lệ vì đây là cách chúng ta truy cập các biến tĩnh trong java, và ra là một đối tượng của PrintStream và do đó chúng ta có thể truy cập vào các phương pháp của nó, Nói tóm lại là

System.out.pritnln(); 

ông hỏi tôi để mô phỏng một loại tương tự của chương trình, tôi bắt nguồn từ và nó đã không làm việc, kể từ System.out đang trở lại vô

câu hỏi của tôi là ở đâu ra đối tượng thuyết minh trong java ? Nó là một đối tượng được xác định trước nếu tôi không sai. những gì nên được giải thích tỉ mỉ cho việc này.

Về mặt kỹ thuật, chúng ta nên gọi ra điều gì? Có phải là một loại biến kiểu PrintStream hay một người nên nói nó như là một đối tượng của kiểu PrintStream?

+1

Ý của bạn là gì bởi "System.out đang trả lại giá trị rỗng"? –

+0

Tôi đã tạo một chương trình tương tự như lớp A {static B out}; lớp B {} Tôi đã cố gắng để in System.out.println (A.out); được trả về null. – srk

Trả lời

20

System.out được khởi tạo thành null khi lớp được khởi tạo. Điều này được đặt theo phương pháp nullPrintStream() trong System.java, chỉ trả về null.

Khi JVM đã khởi tạo, nó gọi phương thức initializeSystemClass(). Phương thức này gọi phương thức nativesetOut0() đặt biến số out thành giá trị thích hợp.

Điều này có vẻ kỳ lạ nhưng nó là một hoạt động cần thiết vì những lý do sau đây:

  • out không thể được đặt tĩnh với giá trị vì System nhu cầu là một trong các lớp được nạp đầu tiên (trước PrintStream).
  • out phải là final để giá trị của nó không thể bị người dùng ghi đè trực tiếp.
  • Vì không thể đặt tĩnh out và cuối cùng, chúng tôi phải ghi đè ngữ nghĩa của ngôn ngữ bằng cách sử dụng phương thức native, setOut0().

Tôi hy vọng điều đó sẽ giúp bạn hiểu.

6

System.out là một thuộc tính tĩnh bình thường, nó được thành lập bởi JVM thông qua phương pháp initializeSystemClass() trong JVM khởi tạo. Bạn thậm chí có thể thay đổi (mặc dù nó không được khuyến nghị) bằng cách gọi System.setOut(printOutStream);, trong đó printOutStream là luồng bạn muốn sử dụng làm đầu ra tiêu chuẩn.

Đây là một chi tiết đẹp article chi tiết cách System.out.println() hoạt động.

+1

Thực ra 'out' được thiết lập bởi JVM thông qua phương thức' initializeSystemClass() '. – Jivings

+0

@Jivings cảm ơn, tôi đã cập nhật câu trả lời của mình. –

-7

System.out.println();

đây println là đối tượng của lớp instream.Chúng tôi không thể trực tiếp tạo đối tượng cho lớp in. Out là một đối tượng của lớp hệ thống. ra được gọi là trường trong lớp hệ thống. trong khi gọi system.out nó gián tiếp tạo đối tượng cho lớp in. do đó chúng ta có thể gọi phương thức println() bằng cách sử dụng System.out.prontln().

+7

* Rất nhiều lỗi trong câu trả lời này, gần như quá nhiều để đếm. Bỏ qua. –

+3

Surendar, println() không phải là một đối tượng mà là một phương thức của lớp PrintStream. –

+2

Bạn có thể trực tiếp tạo một đối tượng cho lớp PrintStream. Ví dụ: http://docs.oracle.com/javase/1.5.0/docs/api/java/io/PrintStream.html#PrintStream%28java.io.File%29. –

0

Trong thư viện thời gian chạy Oracle Java, nó được khởi tạo nguyên gốc bằng phương pháp gốc registerNatives() được gọi (thông qua trình khởi tạo static) khi tải lớp System. Tuy nhiên, đây là một chi tiết thực hiện.

Bạn cũng có thể đặt System.out trực tiếp bằng cách sử dụng System.setOut().

+0

Điều này có đúng không? Bởi vì 'registerNatives()' liên kết các phương thức gốc với các phương thức nội bộ JVM, tôi chưa bao giờ thấy nó được sử dụng để khởi tạo các biến. – Jivings

4

System.out.println() -

Với ý nghĩ đó, chúng ta hãy phá vỡ này xuống, bắt đầu với các nhà điều hành chấm. Trong Java, toán tử dấu chấm chỉ có thể được sử dụng để gọi các phương thức và các biến để chúng ta biết rằng ‘out’ phải là một phương thức hoặc một biến. Bây giờ, làm cách nào để phân loại ‘ra’? Vâng, ‘out’ không thể là một phương pháp vì thực tế là không có dấu ngoặc đơn - ‘()’ - sau ‘out’, có nghĩa là rõ ràng không phải là một phương thức được gọi. Và, ‘out’ không chấp nhận bất kỳ đối số nào bởi vì chỉ có các phương thức chấp nhận các đối số - bạn sẽ không bao giờ thấy một cái gì đó như “System.out (2,3) .println”. Điều này có nghĩa là ‘ngoài’ phải là một biến.

'out' đang được gọi với tên lớp 'Hệ thống' và không phải là một thể hiện của lớp (đối tượng), sau đó chúng tôi biết rằng 'out' phải là biến tĩnh, vì chỉ có biến tĩnh chỉ được gọi với tên lớp. Vì vậy, bây giờ chúng ta biết rằng ‘out’ là một biến thành viên tĩnh thuộc lớp System.

Nhận thấy thực tế là ‘println()’ rõ ràng là một phương pháp, chúng tôi có thể phân loại thêm ‘out’ trong System.out.println(). Chúng tôi đã lý luận rằng ‘out’ là một biến tĩnh thuộc về hệ thống lớp. Nhưng bây giờ chúng ta có thể thấy rằng ‘out’ phải là một thể hiện của một lớp, bởi vì nó đang gọi phương thức ‘println()’.

Quy trình suy nghĩ mà một người nên sử dụng để đi đến câu trả lời được minh họa một cách cố ý ở trên. Nếu không biết câu trả lời chính xác trước, bạn có thể đến một câu trả lời gần đúng bằng cách áp dụng một số kiến ​​thức cơ bản về Java. Hầu hết những người phỏng vấn sẽ không nghĩ rằng bạn biết cách System.out.println() hoạt động ra khỏi đỉnh đầu của bạn, nhưng thà thấy bạn sử dụng kiến ​​thức Java cơ bản của bạn để đi đến một câu trả lời gần đúng.

Câu trả lời chính xác hơn cho câu hỏi ban đầu là: bên trong lớp Hệ thống là khai báo 'out' trông giống như: 'public static final PrintStream out', và bên trong lớp Prinstream là khai báo 'println () 'có chữ ký phương thức trông giống như:' public void println() '.

Đây là những phần khác nhau của System.out.println() thực sự trông giống như:

//the System class belongs to java.lang package 

class System { 
    public static final PrintStream out; 
    //... 
} 

//the Prinstream class belongs to java.io package 
class PrintStream{ 
public void println(); 
//... 
} 
0

Bạn không cần phải truy cập mạng và tài liệu ngay cả. Chúng ta có thể chỉ cần nói javap java.lang.System này cung cấp cho bạn danh sách tất cả các trường tĩnh, các nguyên mẫu phương thức thuộc về lớp System. Chúng ta có thể lấy thông tin chi tiết về bất kỳ lớp java nào bằng cách sử dụng javap, miễn là bạn biết gói và tên lớp của nó là là đối tượng tĩnh công cộng của PrintStream được định nghĩa trong lớp Hệ thống.

0

Khi lớp Hệ thống được khởi tạo, nó gọi phương pháp initializeSystemClass() của nó, đây là mã:

FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); 
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); 

Trong mã này setOut0() là một chức năng có nguồn gốc thực hiện trong System.c:

JNIEXPORT void JNICALL 
Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream) 
{ 
    jfieldID fid = 
     (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;"); 
    if (fid == 0) 
     return; 
    (*env)->SetStaticObjectField(env,cla,fid,stream); 
} 

này là một mã JNI chuẩn đặt System.out thành đối số được truyền cho nó, phương thức này gọi phương thức native setOut0() để đặt biến ngoài thành giá trị thích hợp.

System.out là cuối cùng, điều đó có nghĩa là không thể đặt thành cái gì khác trong initializeSystemClass() nhưng sử dụng mã gốc có thể sửa đổi biến cuối cùng.

0

là đối tượng PrintStream được định nghĩa trong lớp Hệ thống. được tuyên bố là công khai, tĩnh và cuối cùng.

  • println() là phương thức của lớp PrintStream.
  • Phương thức println() được gọi với đối tượng ngoài.
  • Đối tượng ngoài được gọi với lớp Hệ thống.
Các vấn đề liên quan