class TestNullString {   public static void main(String[] args) {
   // --------- block 1 --------------------------------------------------
      String str = null;
      System.out.println(str);               // output: null (1)
      System.out.println(str + "Test");      // output: nullTest (2)
      System.out.println(str.toString());    // java.lang.NullPointerException (3)   // --------- block 2 --------------------------------------------------
      String str2 = "";
      System.out.println(str2);  
      System.out.println(str2 + "Test");  
      System.out.println(str2.toString());    }
}
在上面这个简单程序的block 1当中, str是一个字符串对象,初始化为null。
1。为什么(1)可以打印出null, 而(3)却报NullPointerException? println()打印的时候不是缺省调用对象的toString()方法的吗?那(1)和(3)应该同时报错,或者同时输出null啊?2。(2)的输出怎么会是nullTest? 感觉象字符串连接"null" + "Test" 一样,可str明明是null而不是"null"。按照我的想法,至少应该输出"Test"啊?如果str初始化为空字符串(block 2),则一切正常。但是关于block 1的现象在书上找不到解释,请哪位大侠不吝赐教。谢谢

解决方案 »

  1.   

    (1)System.out.println(str)方法:
    public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
        }
       print(x) 方法:
     public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
        }
      

  2.   

    String str = null; 在内存中没有分配地址
    str + "Test"  会产生一个新的String并分配地址  System.out.println(str + "Test");其实是打印新的那个StringString一旦初始化  就无法改变  在内存中已经分配好了地址
    如果要改变String 就会产生一个新的String 并把改变后的String指向新String的地址。String = ""; 也算是分配了内存了
    跟String=null完全2个事情
      

  3.   

    (3)
       String里面
        public String toString() {
    return this;
        }
    就是说,必须得是一个String对象才行。而null,它啥都不是。
      

  4.   

    空值去.toString()当然会报空指针
      

  5.   

    我明白为什么(1)输出null了,不过这又产生另外一个问题,println(String x)只是针对字符串,如果只是一个object呢?比如
          Object obj = null;
          System.out.println(obj);
    还是输出null啊?
      

  6.   

    string immutable的道理我明白,""和null的区别我也知道。我也明白你说的
    System.out.println(str + "Test");其实是打印新的那个String我不懂的是新字符串"nullTest"是怎样产生的,为什么不是"Test"呢?谢谢
      

  7.   

    应该是String对象的toSting方法和默认直接调用对象的toString方法的区别,开始拿到直接打印调用的是对象引用的tostring方法获取该对象的引用地址,打印是这个对象的内存地址,虽然String对toString方法重写了,但是当你调用时候先调用子类的toString方法,调用失败,然后调用了父类的toString方法,所以得到的是一个null,当你直接调用这个对象的toString方法时候,由于该对象引用并不存在,所以才会抛出空指针错误,建议楼主去看下API里面的toString方法和String类里面的toString方法应该就理解了
      

  8.   


    我比较笨,看了jdk源码里面这两个方法,啥都看不出来
      

  9.   

    补充下  在程序运行之后当你对一个对象调用一个方法的时候JVM会自动去找这个对象 当找不到这个对象时候会报空指针错误  而你上面的那个打印只是打印这个引用  由于对象引用的不存在所以指示为空,楼主这次明白了吧?
      

  10.   

    public class T{
    public static void main(String [] args){
    E obj = null; 
          System.out.println(obj);
          try{
          System.out.println(obj.toString()); 
        } catch(Exception e){
         e.printStackTrace();
        }    
    }

    }
    class E{
    public String toString(){
        return "我是空指针!";
    }
    }
      

  11.   

    哎,最好是找那个写JDK得人来解释这个问题了~~~~~
      

  12.   

       我来终结这道题:
       (1)System.out.println(str)方法: 
           public void println(String x) { 
             synchronized (this) { 
                 print(x); 
                 newLine(); 
             } 
          } 
      (2)print(x) 方法: 
           public void print(String s) { 
             if (s == null) { 
                s = "null"; 
             } 
             write(s); 
         }                  //copy自crazylaa,表示感谢
      (3)对于"a+b",是这么处理的,如果a和b就基本数据类型,则调用String.valueOf(a),String.valueOf(b),得到两个字符串直接连接起来;如果a和b是object类型包括String类型,则首先判断a和b是否等于null,如果等于则把把它们都转化成字符串“null”,再连接起来,如果不等于null,则调用String.valueOf(a),String.valueOf(b)得到两个字符串连接起来----其他各种情况同理
      

  13.   

    引用类型的值有两种含义:引用所指对象的内存地址和引用所指对象的内容。
    String str = null;
    表示的是 str 所指对象的内存地址为 null;
    String str = "Test";
    表示的是 str 所指对象的内存地址是一个字符串对象的地址,并且这个字符串对象的toString方法返回"Test"。// 例1
    String str = null;
    System.out.println(str);例1打印时,JVM发现str所指对象的内存地址为null,JVM针对此类引用直接返回字符串"null"。
    所以你看到的是 null 。// 例2
    String str = null;
    System.out.println(str.toString());例2打印时,JVM将调用str所指对象的toString()方法,但是str所指对象是null,所以JVM抛出NullPointException。
    所以你看到的是抛出 NullPointException 异常。// 例3
    String str = null;
    String str2 = "Test";
    System.out.println(str + str2);当out.println参数中含有+时,JVM内部使用了StringBuilder的append方法。也就是说:
    例3可以分解为String str = null;
    String str2 = "Test";
    StringBuilder sb = new StringBuilder();
    sb.append(str);
    sb.append(str2);
    System.out.println(sb.toString());所以你会看到 nullTest 的结果。// 例4 引申(JVM如何进行 + - * / 等简单运算,自己思考吧。)
    int i = 10;
    int j = 20;
    String str = null;
    System.out.println(i + j + str);例4会打印出什么呢?
    例4可以分解为int i = 10;
    int j = 20;
    String str = null;
    StringBuilder sb = new StringBuilder();
    int c = i + j;
    sb.append(c);
    sb.append(str);
    System.out.println(sb.toString());
      

  14.   


    你改为Object和之前的String是一样的,关键是后面的null没变,你还记得有个问题是这样的,
    String str = new String("abc");
    这句话产生了几个对象吗?
    换作Object obj = null;
    只是产生了一个对象obj,然后指向null.而null依然啥都不是.
    明白否?
      

  15.   

    // --------- block 1 -------------------------------------------------- 
          String str = null; 
          System.out.println(str);              // output: null (1)字符串没赋值的时候打印null
          //表示未赋值
          System.out.println(str + "Test");      // output: nullTest (2) 
          System.out.println(str.toString());    //java.lang.NullPointerException (3)
    //你设置的str=null是表示你的str没有赋值,而str=""表示str赋空值,所以当你用tostring()方法返回
    //字符串本身时,找不到str指向的值,所以返回空指针异常
    // --------- block 2 -------------------------------------------------- 
          String str2 = ""; 
          System.out.println(str2);  
          System.out.println(str2 + "Test");  
          System.out.println(str2.toString()); //
      

  16.   


    换作Object obj = null;
    这里有产生对象吗?只是在将一个对象变量=null,并没有产生对象吧
      

  17.   

    public String toString()返回此对象本身(它已经是一个字符串!)。 
      

  18.   

    // --------- block 1 -------------------------------------------------- 
          String str = null; 
          System.out.println(str);              // output: null (1)字符串没赋值的时候打印null 
          //表示未赋值 
          System.out.println(str + "Test");      // output: nullTest (2) 
          System.out.println(str.toString());    //java.lang.NullPointerException (3) 
    //你设置的str=null是表示你的str没有赋值,而str=""表示str赋空值,所以当你用tostring()方法返回 
    //字符串本身时,找不到str指向的值,所以返回空指针异常 
    // --------- block 2 -------------------------------------------------- 
          String str2 = ""; 
          System.out.println(str2);  
          System.out.println(str2 + "Test");  
          System.out.println(str2.toString()); // 
     
    上面那个事我的另一个号,用错号了,lz要给分请给我这个号(去下载实在是太费分了,现在评论还不给分了郁闷,一切为了混的更好)
      

  19.   

    obj没有实例化,执行System.out.println(obj)时是打印出obj.toString()的值的,所以打印出null。
    如果obj实例化了,那就会打印出obj指向的地址值。
      

  20.   

    (1)由于你初始化的str是null,也就是说java虚拟机没有给它分配地址,如果将它输出虚拟机就会把没有分配地址的str的值置为null,想这是你明白的。
    (2)即如果你已经明白(1)为什么输出了,也就是str的值虚拟机会将它置为null,当然"null"+"Test"==nullTest。
    (3)str.toString() 它的意思是将str地址中的值转换成String类型。但是str的地址是不存在的,也就是说要将一个值转换,但根本就找不到它,则会有空指针异常。
      

  21.   

    String str = null; 在内存中没有分配地址
    所以不能用str.toString()方法,没有分配空间的对象都不能调用该对象的方法,否者会出现npe异常
      

  22.   

    null的对象如何调用方法?
    这样当然就是空指针异常
      

  23.   

    JDK API
    String str = null;        //public void println(String x)  打印 String,然后终止该行。
    //此方法的行为就像先调用 print(String)然后调用 println()一样。

    /*public void print(String s)
         打印字符串。如果参数为 null,则打印字符串 "null"。
        否则,按照平台的默认字符编码将字符串的字符转换为字节,
        并完全以 write(int) 方法的方式写入这些字节。
    */
    Object o = null;        //public void println(String x) 打印 String,然后终止该行。
    //此方法的行为就像先调用 print(String) 然后调用 println() 一样。

    //public void print(Object obj)
    //打印对象。按照平台的默认字符串编码将 String.valueOf(Object) 
    //方法生成的字符串转换为字节,并完全以 write(int) 方法的方式写入这些字节。

    /*
            public static String valueOf(Object obj)
    返回 Object 参数的字符串表示形式。
    参数:
    obj - 一个 Object。
    返回:
    如果参数为 null,则字符串等于 "null";否则,返回 obj.toString() 的值。
    */
    问题1.println()并不是直接调用 .toString()方法,而是要先判断是否为null。
    (3)因为对象不存在,所以你调用对象的任何方法都会抛出空指针异常。问题2.字符串的连接操作在JVM中是通过StringBuilder 的append()方法来实现的,即先建立一个StringBuilder 对象s,然后调用s.append()方法把字符串添加到末尾,可以参看Thinking in java的字符串一章开始的部分。append()遇到null的操作如下: /*
    public StringBuilder append(StringBuffer sb)
    将指定的 StringBuffer 追加到此序列。
    按顺序追加 StringBuffer 参数中的字符,此序列将增加该参数的长度。
    如果 sb 为 null,则向该序列中追加 4 个 "null" 字符。 在执行 append 方法前,让此字符序列的长度为 n。如果 k 小于 n,
    则新字符序列中索引 k 处的字符等于原有序列中索引 k 处的字符;
    否则它等于参数 sb 中索引 k-n 处的字符。 参数:
    sb - 要追加的 StringBuffer。
    返回:
    此对象的一个引用。
    */
      

  24.   

    对不起,我17楼写的不太对,
    刚试了试
          System.out.println(2+3);   打出来会是5
    我还以为会是23呢,我都是想当然的推测的,搞错了,请大家把我写的忘记把,实在不好意思18楼说的才对
      

  25.   

    System.out.println("2"+"3");才是23,不想都知道