问题描述
由于工作面向银行客户,开发的工作内容主要是调用行方接口,将接口返回的数据在界面上显示。由于接口文档未及时维护,文档中偶尔会将数据类型记录错误。比如:
1、返回字段文档中标记为“字符”类型,但是实际返回的是“数字”类型。
2、某个字段接口未返回、返回为空字符串、返回为null、返回为字符串"null"。
为了方便处理,统一将接口返回的数据转为字符串展示;在将数据格式转换的过程中,代码里的方法也是五花八门:
1、toString(),当字段为null时会报:java.lang.NullPointerException。
2、(String)强转,当数据类型不一致时会报转换异常。
3、+""
4、String.valueOf()
比较区别
1、toString()
Object object = new Object ();
System.out.println(object.toString());
因为java.lang.Object类里有.toString()方法,所以对任何的java对象都可以调用此方法。但在使用时要注意,必须保证object不是null值,否则将抛出NullPointerException异常。采用这种方法时,通常派生类会重写覆盖Object里的toString()方法。
2、 (String)object
这是标准的类型转换,将object转成String类型的值。使用这种方法时,需要注意的是类型必须能转成String类型。因此最好用instanceof做个类型检查,以判断是否可以转换,否则容易抛出CalssCastException异常。
(1)null值可以进行强转,转换后仍为null,(String)null也是合法的。
(2)此外,需特别小心的是因定义为Object类型的对象(可能为非string对象)在转成String时语法检查并不会报错,这将可能导致潜在的错误存在。
(3)显示的将非String对象强转为String在编译时会报语法错误。
String a = null;
String b = (String)a;
System.out.println(b == null);// true
Object obj = new Integer(100);
String strVal = (String)obj;// 编译通过,运行时报:CalssCastException
Integer obj2 = new Integer(100);
String strVal2 = (String)obj2;// 编译时报错
3、String.valueOf(Object)
String.valueOf(Object)的基础是Object#toString(),Jdk里源码如下:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
采用这种方法时,将不用担心object是否为null值这一问题,但是,这也恰恰给了我们隐患。我们应当注意到,当object为null,String.valueOf(object)的值是字符串”null”,而不是null!!!
在使用过程中切记要注意。
Object object = null;
// 错误
if(String.valueOf(object) == null){
System.out.println(“传入的值是null!”);
}
// 正确
if(String.valueOf(object) == "null"){
System.out.println(“传入的值是字符串null!”);
}
试想一下,如果直接控制台输出时,在视觉上如下语句在执行的结果上有什么不同:
System.out.println(String.valueOf(null));
System.out.println(null);
我们看到的输出将是一模一样的东西:null,但意义不一样。这里System.out.println在输出时对null也进行了处理,jdk源码如下:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
4、object + “”
字符串相加,最终输出是String类型,其实这个是运算符重载的结果,任何Object与String相加最终输出是String类型。
但是!请注意,只要是使用相加符号的字符串,都会自动new一个StringBuilder去append,效率上会增加多一个对象的容量消耗,所以建议循环动态拼装字符串时不要使用这种方式去处理字符串,应用stringbuffer代替。
System.out.println("hello" + " world");
String a = "hello";
System.out.println(a + " world");
还有一点值得注意,在平时写代码的时候,为了便于理解,会采用+进行拼装,这种是否影响了运行效率?如果影响了为什么没有人指出?
实际情况是这种做法对效率没有影响,JDK在编译时会做优化,会将"hello" + " world"转成"hello world"。
但是!如果你在额外的地方定义了一个变量在组装时和其它Object类型组装时,同样也会是使用StringBuilder去append。
使用jad反编译工具对class进行测试,结果如下:
解决方法
建议定义一个工具类方法对接口返回字符进行转换,便于后期逻辑调整,工具类中采用string.valueOf (),使用字符串"null" 进行判断是否为空。