《Java解惑》系列——02字符谜题——谜题12:ABC(char[]的重载问题)

知识点:

在日常的编程中,要注意java对char[]的处理。


问题:

下面的程序会打印什么?

public class ABC{
    public static void main(String[] args){
        String letters = "ABC";
        char[] numbers = {'1', '2', '3'};
        System.out.println(letters + " easy as " + numbers);
    }
}

// 期望结果:ABC easy as 123
// 实际结果:ABC easy as [C@16f0472(不一定是这个16进制)

结果是不是出乎大家的意料呢?的确如此。
产生这个结果的原因:

尽管 char 是一个整数类型,但是许多类库都对其进行了特殊处理,因为 char
数值通常表示的是字符而不是整数。例如,将一个 char 数值传递给println 方
法会打印出一个Unicode字符而不是它的数字代码。字符数组受到了相同的特殊
处理:println 的 char[]重载版本会打印出数组所包含的所有字符,而
String.valueOf和StringBuffer.append的char[]重载版本的行为也是类似的。  
然而,字符串连接操作符在这些方法中没有被定义。该操作符被定义为先对它的
两个操作数执行字符串转换,然后将产生的两个字符串连接到一起。对包括数组
在内的对象引用的字符串转换定义如下[JLS 15.18.1.1]:  
如果引用为 null,它将被转换成字符串"null"。否则,该转换的执行就像是不
用任何参数调用该引用对象的 toString方法一样;但是如果调用 toString方法
的结果是 null,那么就用字符串"null"来代替。 
那么,在一个非空char 数组上面调用 toString方法会产生什么样的行为呢?数
组是从Object 那里继承的 toString方法[JLS 10.7],规范中描述到:“返回一
个字符串,它包含了该对象所属类的名字,'@'符号,以及表示对象散列码的一
个无符号十六进制整数”[Java-API]。有关Class.getName 的规范描述到:在
char[]类型的类对象上调用该方法的结果为字符串"[C"。将它们连接到一起就形
成了在我们的程序中打印出来的那个丑陋的字符串。 



解决方法:

那么,在一个非空char 数组上面调用 toString方法会产生什么样的行为呢?数
组是从Object 那里继承的 toString方法[JLS 10.7],规范中描述到:“返回一
个字符串,它包含了该对象所属类的名字,'@'符号,以及表示对象散列码的一
个无符号十六进制整数”[Java-API]。有关Class.getName 的规范描述到:在
char[]类型的类对象上调用该方法的结果为字符串"[C"。将它们连接到一起就形
成了在我们的程序中打印出来的那个丑陋的字符串。  
有两种方法可以订正这个程序。你可以在调用字符串连接操作之前,显式地将一
个数组转换成一个字符串:  
System.out.println(letters + " easy as " +
                       String.valueOf(numbers));
或者,你可以将System.out.println 调用分解为两个调用,以利用 println 的
char[]重载版本:  
System.out.print(letters + " easy as ");
System.out.println(numbers);
请注意,这些订正只有在你调用了 valueOf 和 println 方法正确的重载版本的情
况下,才能正常运行。换句话说,它们严格依赖于数组引用的编译期类型。
 

注意:

下面的程序说明了这种依赖性。看起来它像是所描述的第二种订正方式的具体实
现,但是它产生的输出却与最初的程序所产生的输出一样丑陋,因为它调用的是
println 的 Object重载版本,而不是 char[]重载版本。  
class ABC2{
   public static void main(String[] args){
       String letters = "ABC";
       Object numbers = new char[] { '1', '2', '3' };
       System.out.print(letters + " easy as ");
       System.out.println(numbers);  
   }
}
总之,char 数组不是字符串。要想将一个 char 数组转换成一个字符串,就要调
用String.valueOf(char[])方法。某些类库中的方法提供了对 char 数组的类似
字符串的支持,通常是提供一个 Object版本的重载方法和一个 char[]版本的重
载方法,而之后后者才能产生我们想要的行为。 




总结:

对语言设计者的教训是:char[]类型可能应该覆写toString方法,使其返回数
组中包含的字符。更一般地讲,数组类型可能都应该覆写toString方法,使其
返回数组内容的一个字符串表示。 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值