append进StringBuilder里的字符串是""还是"null"? Java
2016-04-01 19:35
429 查看
有这样一个需求:有一个类,它有几个域,希望它的toString方法返回它的所有域的值组合成的字符串,域值之间用某种分隔符(比如####)分隔。我是这样实现的:
当运行这个类的时候,我希望的输出是:
而实际上是:
为什么实际的输出和期望的不一样呢?看看StringBuilder的append(String)方法的源码:
继续查看它父类的append(String)方法的源码:
原来如此,当字符串为null时,就被当做”null”处理。因为我知道,如果没有显式的给CombineFieldWithDelimiter 类的各个域赋值,它们都将是null,所以,问题就明了了。为了解决问题,我只需显式的给每个域赋字符串”“就可以了,像下面这样:
如果同学们对虚拟机中对象的创建过程不太了解,这里简单介绍一下。当我们new一个对象时,虚拟机首先去检查要创建对象的类是否已经加载(包括加载、连接和初始化)了,如果没有,就执行相应的类加载过程;然后虚拟机就给对象分配内存并把分配的内存空间都初始化为零值,给内存空间赋零值得操作使得对象的实例字段可以在不赋初始值的情况下也能直接使用,但都是相应的零值,对于对象域来说,就是null,理解了这一点,才算是真正理解本文了;最后是执行对象初始化方法<init>,给对象的域赋上程序员指定的值,例如,在我对上CombineFieldWithDelimiter的代买进行修改后,下面的语句执行后,
field1的值不是null,而是“”了。当执行完成后,一个真正可用的对象才算完全产生出来。
public class CombineFieldWithDelimiter { private String field1; private String field2; private String field3; public CombineFieldWithDelimiter() { } @Override public String toString() { String delimiter ="####"; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(delimiter); stringBuilder.append(field1); stringBuilder.append(delimiter); stringBuilder.append(field2); stringBuilder.append(delimiter); stringBuilder.append(field3); return stringBuilder.toString(); } public void setField1(String field1) { this.field1 = field1; } public void setField2(String field2) { this.field2 = field2; } public void setField3(String field3) { this.field3 = field3; } public static void main(String[] args) { CombineFieldWithDelimiter combineFieldWithDelimiter = new CombineFieldWithDelimiter(); System.out.println(combineFieldWithDelimiter.toString()); } }
当运行这个类的时候,我希望的输出是:
########
而实际上是:
null####null####null
为什么实际的输出和期望的不一样呢?看看StringBuilder的append(String)方法的源码:
public StringBuilder append(String str) { super.append(str); return this; }
继续查看它父类的append(String)方法的源码:
public AbstractStringBuilder append(String str) { // null字符串当做"null"处理 if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; }
原来如此,当字符串为null时,就被当做”null”处理。因为我知道,如果没有显式的给CombineFieldWithDelimiter 类的各个域赋值,它们都将是null,所以,问题就明了了。为了解决问题,我只需显式的给每个域赋字符串”“就可以了,像下面这样:
public class CombineFieldWithDelimiter { private String field1 = ""; ... }
如果同学们对虚拟机中对象的创建过程不太了解,这里简单介绍一下。当我们new一个对象时,虚拟机首先去检查要创建对象的类是否已经加载(包括加载、连接和初始化)了,如果没有,就执行相应的类加载过程;然后虚拟机就给对象分配内存并把分配的内存空间都初始化为零值,给内存空间赋零值得操作使得对象的实例字段可以在不赋初始值的情况下也能直接使用,但都是相应的零值,对于对象域来说,就是null,理解了这一点,才算是真正理解本文了;最后是执行对象初始化方法<init>,给对象的域赋上程序员指定的值,例如,在我对上CombineFieldWithDelimiter的代买进行修改后,下面的语句执行后,
CombineFieldWithDelimiter combineFieldWithDelimiter = new CombineFieldWithDelimiter();
field1的值不是null,而是“”了。当执行完成后,一个真正可用的对象才算完全产生出来。
相关文章推荐
- Swift语言精要 - Operator(运算符重载)
- Swift语言精要 - 扩展(Extension)
- 复制文件时,如何显示进度条(使用BlockRead函数读取数据,并插入application.ProcessMessages)
- Unity Flow distort of screen
- Android Studio 常用快捷键
- Android上实现仿IOS弹性ScrollView
- Swift语言精要 - 属性
- Android开发之内存管理
- Android Fragment完全解析
- leetcode 202. Happy Number
- Understanding the Android Source Code
- Android开发点滴 - 如何使按钮水平垂直居中且始终占据屏幕宽度一半
- android 基础 getTag,setTag的用法
- Android开发中adb启动失败adb连接异常的解决办法
- 深入浅出Android动态载入jar包技术
- Android游戏开发之数据库SQLite 详细介绍(十七)
- Appium中部分api的使用方法
- cocos2d-x 3.4版本 Android ndk-gdb真机调试环境搭建
- Android MTK 锁屏时间显示显示不全修改
- 选择cocos2d-js的原因,摘录了官网的一些东西