[转帖]由一个简单的String c=a+b的Java问题引发一点想法_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3867 | 回复: 0   主题: [转帖]由一个简单的String c=a+b的Java问题引发一点想法        下一篇 
ab19890824
注册用户
等级:少尉
经验:351
发帖:92
精华:0
注册:2011-11-21
状态:离线
发送短消息息给ab19890824 加好友    发送短消息息给ab19890824 发消息
发表于: IP:您无权察看 2011-11-27 20:37:03 | [全部帖] [楼主帖] 楼主

今天在我的一个qq群里有人问了这样一个问题。

  1. private static String a;
  2. private static String b;
  3. public static void main(String[] args) {
  4.   String c = a+b;
  5.   System.out.println(c);
  6. }

输出是”nullnull”。问为什么是这样。

其实问题并不复杂,很多同学也觉得自己知道原因,遂不予关注。但是我相信还是有初学Java的同学在这里是存在误会的。很典型的误会就是如一个群里的朋友说的String类型的变量如果没有显示初始化,默认的值就是”null”。支持的理由就是

  1. private static String a;
  2. public static void main(String[] args) {
  3.   System.out.println(a);
  4. }

输出是“null”。

这个现实确实很容易迷惑一些初学的人,包括我也忽略了挺久。其实呢证明这种想法错误很简单。如果默认值是“null”,那么就意味着,该变量不是空(null)。而是字符串的”null”。

  1. private static String a;
  2. public static void main(String[] args) {
  3.   System.out.println(a==null);
  4.   System.out.println("null".equals(a));
  5. }


上述代码输出分别是true,false

说明String类型变量a,其实是空(null),而并没有被赋值。那么打印出null是为什么呢?我们查看PrintStream的源码就很清晰的明白了,其实是Java在println的时候进行了处理。

  1. public void print(String s) {
  2.   if (s == null) {
  3.   s = "null";
  4.   }
  5.   write(s);
  6. }


回到开头的问题,既然没有初始化赋值,那么输出为什么是”nullnull”,两个”null”连接的结果呢。这里略微细说一下,查看编译过的class文件,我们可以看到

  1. public static void main(java.lang.String[] args);
  2. 0 new java.lang.StringBuilder [19]
  3. 3 dup
  4. 4 getstatic cn.home.pratice.jdk.string.StringMain.a : java.lang.String [21]
  5. 7 invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [23]
  6. 10 invokespecial java.lang.StringBuilder(java.lang.String) [29]
  7. 13 getstatic cn.home.pratice.jdk.string.StringMain.b : java.lang.String [32]
  8. 16 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [34]
  9. 19 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [38]
  10. 22 astore_1 [c]
  11. 23 getstatic java.lang.System.out : java.io.PrintStream [42]
  12. 26 aload_1 [c]
  13. 27 invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
  14. 30 return System.out.println(c);
  15. }

String的相加实际在变异后被处理成了StringBuilder的append.(注:我的JDK是1.6.0_u29)。那么好,我们就应该查看StringBuilder的源码,发现是调用的父类里的方法,继续查看,道理就在这里。

  1. public StringBuilder append(String str) {
  2.   super.append(str);
  3.   return this;
  4. }
  5. public AbstractStringBuilder append(String str) {
  6.   if (str == null) str = "null";
  7.   int len = str.length();
  8.   if (len == 0) return this;
  9.   int newCount = count + len;
  10.   if (newCount > value.length)
  11.   expandCapacity(newCount);
  12.   str.getChars(0, len, value, count);
  13.   count = newCount;
  14.   return this;
  15. }

原来也是对空null,进行了特殊的处理,那么输出是”nullnull”,自然也就明白了。

这里我想说的是,很多问题,可能表面上很简单,或者我们可能会有很多想当然的想法,不过还是眼见为实,而且所有代码都放在那里,我们为什么不勤快的多翻开看看其中的实现,道理自然就在眼前。多动手,丰衣足食:)




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论