我看不懂这句话public final static PrintStream out = nullPrintStream();,能帮忙解释一下吗?

解决方案 »

  1.   

    定义PrintStream型全局静态常量out,并将nullPrintStream()方法的返回值赋给out
      

  2.   

    谢谢
    System.out.println里的out到底是普通字段还是对象?
    如果是普通字段(属性),那么System.out.println这样的写法是不成立的吧?我看了System类的源码,我发现是把out定义为普通对象的
    而在System类的源码里,并没有println这个方法啊
      

  3.   

    System.out.println
    调用System里面的out
    再调用out里面的println
    out是PrintStream类型,所以要到PrintStream类里找println
      

  4.   

    谢谢,我看不明白,这个out到底是对象,还是普通字段
    看定义,似乎是普通对象吧public   final   static   PrintStream   out   =   nullPrintStream();
      

  5.   

    是的,字段可以是基本类型,也可以是对象类型
    如下定义似乎是一个对象类型
    可是这个out为什么不是PrintStream out = new PrintStream()呢?
    而是,我看了不解
    public final static PrintStream out = nullPrintStream(); 
      

  6.   

    System类里有大量的native方法,是调用本地代码的,这些代码很可能是由虚拟机来调用的. 
    System类的开头有一段:
    static { 
        registerNatives(); 

    这段代码会在虚拟机启动的时候就执行,它在虚拟机里注册System需要使用的一些本地代码 
    比如:
    private static native Properties initProperties(Properties props); 
    private static native void setOut0(PrintStream out); 
    在windows下的话,它就告诉虚拟机到哪个dll文件里去找相应的实现
    /** 
    * The following two methods exist because in, out, and err must be 
    * initialized to null. The compiler, however, cannot be permitted to 
    * inline access to them, since they are later set to more sensible values 
    * by initializeSystemClass(). 
    */ 
    private static InputStream nullInputStream() throws NullPointerException { 
    if (currentTimeMillis() > 0) 
    return null; 
    throw new NullPointerException(); 
    }
    也就说in, out, and err 初始化为null,然后会在后来由initializeSystemClass()方法类初始化成有意义的值/** 
    * Initialize the system class. Called after thread initialization. 
    */ 
    private static void initializeSystemClass() { 
    props = new Properties(); 
    initProperties(props); 
    sun.misc.Version.init(); 
    FileInputStream fdIn = new FileInputStream(FileDescriptor.in); 
    FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); 
    FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); 
    setIn0(new BufferedInputStream(fdIn)); !!! 
    setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); !!! 
    setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); !!! // Enough of the world is now in place that we can risk 
    // initializing the logging configuration. 
    try { 
    java.util.logging.LogManager.getLogManager().readConfiguration(); 
    } catch (Exception ex) { 
    // System.err.println("Can´t read logging configuration:"); 
    // ex.printStackTrace(); 
    } // Load the zip library now in order to keep java.util.zip.ZipFile 
    // from trying to use itself to load this library later. 
    loadLibrary("zip"); // Subsystems that are invoked during initialization can invoke 
    // sun.misc.VM.isBooted() in order to avoid doing things that should 
    // wait until the application class loader has been set up. 
    sun.misc.VM.booted(); 
    }
    in,out,err就是在以上方法以下三条语句里初始化的.setIn0(new BufferedInputStream(fdIn)); !!! 
    setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); !!! 
    setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); !!! 

    private static native void setIn0(InputStream in); 
    这是个native函数,是前面registerNatives()的时候注册了的.这个函数应该是把实际连接到输入输出设备的句柄传给虚拟机并赋值给in,out,err 这么解释明白了吗?
      

  7.   

    谢谢
    不明白,更糊涂了
    不明白什么是native函数
    不明白建立对象为什么不用new
      

  8.   

    其实在
    private static InputStream nullInputStream() throws NullPointerException
    方法的说明里已经告诉我们为什么这么写了,简单的说它要先被初始化成null,然后再由initializeSystemClass()
    方法初始化。
    好好研究一下下面这段英文
    /**
         * The following two methods exist because in, out, and err must be
         * initialized to null.  The compiler, however, cannot be permitted to
         * inline access to them, since they are later set to more sensible values
         * by initializeSystemClass().
         */
    累啊,楼主,牺牲了我午休的时间...
      

  9.   

    谢谢,我是初学者,不太明白
    既然out是一个对象,为什么不用new?影响你午休了,sorry
      

  10.   

    你可以简单理解它是在nullPrintStream()方法里new的,然后把nullPrintStream()里new好的
    赋给out
      

  11.   

    就是一个简单的赋值问题  
    你就理解成String str = disposal();其中disposal是你随便定义的一个函数,只不过该函数返回一个String的值而已....
    你再不理解就去看书吧....
      

  12.   

    非常感谢olivesoup
    这样说似乎能理解了,可是为什么不直接new呢?
    建立对象似乎除了new还有别的方法?
      

  13.   

    因为那里并不需要一个真正的new PrintStream();给个null就可以满足要求,
    不然不是浪费系统开销嘛。
    建立对象可以直接A a = new A();
    也可以丛一个函数中得到返回值,但归根结底你可以简单理解为都是new出来的啥时候结贴给分啊?
      

  14.   

    LZ有什么想不明白的
    out肯定是对象,这点不用怀疑。
    给你举个简单的例子,明白了你就明白你的问题了public class A {
        public final static PrintStream out = nullPrintStream(); //nullPrintStream是个方法,返回值是PrintStream对象     public static PrintStream nullPrintStream() {
            //return new PrintStream(); 
            return null; //new一个对象返回还是返回空对象,由写程序的人决定
        }    public static void setOut(PrintStream o) {
            out = o; //给out赋值
        }    public static void main(String[] args) {
            setOut(new PrintStream());
            out.println("hello");
        }
    }
      

  15.   

    不好意思,忽略了小细节
    public class A {
        //把final去掉,否则常量就不能再改变了
        public static PrintStream out = nullPrintStream(); //nullPrintStream是个方法,返回值是PrintStream对象     public static PrintStream nullPrintStream() {
            //return new PrintStream(); 
            return null; //new一个对象返回还是返回空对象,由写程序的人决定
        }    public static void setOut(PrintStream o) {
            out = o; //给out赋值
        }    public static void main(String[] args) {
            setOut(new PrintStream());
            out.println("hello");
        }
    }在java的层次上,建立一个对象,除了new和反射的newInstance以外,应该没有别的方法了
    这里用setOut可以给out赋值,但这个赋值这个对象也是new出来的,native方法内部,应该也是new一块内存出来的
      

  16.   

    似乎有点明白吧
    都怪我理解能力太差,
    要么显式地new
    要么用方法赋值,方法的返回值是一个对象,相当于隐式地new了