Как работает System.out.println() ?

 
 
 
Сообщения:1
Привет всем, в Java, как и в программировании в целом являюсь новичком, совсем недавно начал изучать. Вопрос в следующем:
System - это класс, в котором есть статическое поле out типа PrintStream. То есть, когда мы пишем System.out, мы обращаемся к нему. Это понятно. Но, в out лежит null. То есть, в моем понимании, при попытке вызова любого метода у out, должна выйти ошибка NPE, но все прекрасно работает. Прошу объяснить, почему.
 
 
Сообщения:1558
В комментариях класса System можно все это найти
 static {
        registerNatives();
    }

Вызываем эту функцию, над ней есть комментарий
 /* register the natives via the static initializer.
     *
     * VM will invoke the initializeSystemClass method to complete
     * the initialization for this class separated from clinit.
     * Note that to use properties set by the VM, see the constraints
     * described in the initializeSystemClass method.
 */

Смотри данную функцию

 /**
     * Initialize the system class.  Called after thread initialization.
     */
    private static void initializeSystemClass() {
     ...
        FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
     ...
        setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));

где
    private static native void setOut0(PrintStream out); // функция позволяющая менять статик переменную
   public static final FileDescriptor out = standardStream(1);// 1 это стандартный вывод
       private static FileDescriptor standardStream(int fd) {
        FileDescriptor desc = new FileDescriptor();
        desc.handle = set(fd);
        return desc;
    }


Если уж совсем интересно,то можно залезть в сорцы джавы и найти данный метод
/*
 * The following three functions implement setter methods for
 * java.lang.System.{in, out, err}. They are natively implemented
 * because they violate the semantics of the language (i.e. set final
 * variable).
 */
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);
}
Изменен:10 авг 2018 15:27
 
Модераторы:frymock
Сейчас эту тему просматривают:Нет