故事背景

一座普普通通的小屋里,住着大头儿子、小头爸爸和围裙妈妈。在他们普普通通的生活中,总是响起充满欢乐的笑声。最温暖的家又成了他们每个人的爱的源泉。

《大头儿子和小头爸爸》是孩子居首(大头),妈妈居中,爸爸最末(小头);爸爸主外,妈妈主内(围裙),他们是中国现代家庭教育典型的缩影。

java中的大头儿子和小头爸爸

java中也有一对冤家对头,他们就是字符char和字符串String。来看看他们的表现吧:                                               

        System.out.println("h"+"i");
System.out.println('h'+'i');

会打印出什么呢?结果可能出乎你的意外:

hi
209

为什么会出现209这个结果呢?

编译器在计算常量表达式'h'+'i'时,是通过我们熟知的拓宽原始类型转换将两个具有字符型数值的操作数('h'和'i')提升为int 数值而实现的。从char 到int 的拓宽原始类型转换是将16 位的char 数值零扩展到32 位的int。对于'h',char 数值是104,而对于'i',char 数值是105,因此表达式'h'+'i'等价于int常量104 + 105,或209。

有三种方式避免出现char的连接问题。第一种最简单:

System.out.println("" + 'h' + 'i');

第二种:使用函数

System.out.printf("%c%c", 'h', 'i');
或者
System.out.println(String.format("%c%c", 'h','i'));

第三种,利用api拼装:

StringBuffer sb = new StringBuffer();
sb.append('h');
sb.append('i');
System.out.println(sb);

也会你会认为这比较简单,那我们就见识一个比较复杂点的吧!

    private static Random rnd = new Random();
public static void main(String[] args) {
StringBuffer word = null;
switch(rnd.nextInt(2)) {
case 1: word = new StringBuffer('P');
case 2: word = new StringBuffer('G');
default: word = new StringBuffer('M');
}
word.append('a');
word.append('i');
word.append('n');
System.out.println(word);
}

乍一看,这个程序可能会在一次又一次的运行中,以相等的概率打印出Pain,Gain 或 Main。看起来该程序会根据随机数生成器所选取的值来选择单词的第一个字母:0 选M,1 选P,2 选G。它实际上既不会打印Pain,也不会打印Gain。也许更令人吃惊的是,它也不会打印Main,并且它的行为不会在一次又一次的运行中发生变化,它总是在打印ain。这又是为什么呢?

多个问题,纠结在一起导致了这个问题:

1.Random.nextInt(int)的规范描述道:“返回一个伪随机的、均等地分布在从0(包括)到指定的数值(不包括)之间的一个int 数值”[Java-API]。这意味着表达式rnd.nextInt(2)可能的取值只有0和1,Switch语句将永远也到不了case2 分支,这表示程序将永远不会打印Gain。nextInt 的参数应该是3 而不是2。

2. case中没有任何break 语句。不论switch 表达

式为何值,该程序都将执行其相对应的case 以及所有后续的case[JLS 14.11]。因此,尽管每一个case 都对变量word 赋了一个值,但是总是最后一个赋值胜出,覆盖了前面的赋值。最后一个赋值将总是最后一种情况(default),即new StringBuffer{'M'}。这表明该程序将总是打印Main,而从来不打印Pain或Gain。

3.在本例中,编译器会选择接受int 的构造器,通过拓宽原始类型转换把字符数值'M'转换为一个int 数值77[JLS 5.1.2]。换句话说,new StringBuffer('M')返回的是一个具有初始容量77 的空的字符串缓冲区。该程序余下的部分将字符a、i 和n 添加到了这个空字符串缓冲区中,并打印出该字符串缓冲区那总是ain 的内容。

修改如下:

    private static Random rnd = new Random();
public static void main(String[] args) {
System.out.println("PGM".charAt(rnd.nextInt(3)) + "ain");
}

参考资料

【1】java解惑

【2】https://baike.baidu.com/item/%E5%A4%A7%E5%A4%B4%E5%84%BF%E5%AD%90%E5%92%8C%E5%B0%8F%E5%A4%B4%E7%88%B8%E7%88%B8/2346537?fromtitle=%E5%A4%A7%E5%A4%B4%E5%84%BF%E5%AD%90%E5%B0%8F%E5%A4%B4%E7%88%B8%E7%88%B8&fromid=3076860&fr=aladdin

大头儿子和小头爸爸的战斗--java字符和字符串的更多相关文章

  1. java字符统计+字符串压缩

    要实习了.突然发现自己好像什么都不会,就去看看题吧.在网上看到一个字符串压缩的题.看了一眼,感觉用python很简单.一个for循环+字典就可以搞定. 但是呢,主要还是java.下面就用java来实现 ...

  2. Java 字符与字符串

    字符 // 定义字符 char c1 = 'a'; char c2 = '1'; char c3 = '中'; // 自动装箱 Character c = c1; // 自动拆箱 c1 = c; // ...

  3. java字符,字符串,数字之间的转换

    string 和int之间的转换 string转换成int  :Integer.valueOf("12") int转换成string : String.valueOf(12) ch ...

  4. 【JAVA编码专题】 JAVA字符编码系列三:Java应用中的编码问题

    这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考. 为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问 ...

  5. 关于JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换

    我们最初学习计算机的时候,都学过ASCII编码. 但是为了表示各种各样的语言,在计算机技术的发展过程中,逐渐出现了很多不同标准的编码格式, 重要的有Unicode.UTF.ISO-8859-1和中国人 ...

  6. 小伙子又乱码了吧-Java字符编码原理总结

    前提 配合前面阅读的I/O和NIO的资料,现在总结一下关于字符集和乱码问题的原理和解决方案.参考资料: 码表ASCII Unicode GBK UTF-8 字符编码笔记ASCII,Unicode和UT ...

  7. java字符编码详解

    引用自:http://blog.csdn.net/jerry_bj/article/details/5714745 GBK.GB2312.iso-8859-1之间的区别 GB2312,由中华人民共和国 ...

  8. JAVA字符编码三:Java应用中的编码问题

    第三篇:JAVA字符编码系列三:Java应用中的编码问题 这部分采用重用机制,引用一篇文章来完整本部分目标. 来源:  Eceel东西在线 问题研究--字符集编码  地址:http://china.e ...

  9. 【字符编码】Java字符编码详细解答及问题探讨

    一.前言 继上一篇写完字节编码内容后,现在分析在Java中各字符编码的问题,并且由这个问题,也引出了一个更有意思的问题,笔者也还没有找到这个问题的答案.也希望各位园友指点指点. 二.Java字符编码 ...

随机推荐

  1. codeforces 814 C. An impassioned circulation of affection(二分+思维)

    题目链接:http://codeforces.com/contest/814/problem/C 题意:给出一串字符串然后q个询问,问替换掉将m个字符替换为字符c,能得到的最长的连续的字符c是多长 题 ...

  2. odoo12从零开始:一、安装odoo运行环境(windows10)

    前言 鉴于好多朋友说没有mac电脑,windows开发其实也差不了多远,只是个人习惯问题,而且吧,windows的电脑其实配环境也挺快的其实,我在这里再稍微补一个比较简单的windows环境部署,希望 ...

  3. Django学习笔记(一):第一个django程序

    1.创建和运行 django-admin startproject xxx python manage.py runserver 2.第一个项目程序 wsgi.py中文名:python服务器网关接口. ...

  4. 《Ansible自动化运维:技术与佳实践》第二章读书笔记

    Ansible 安装与配置 本章主要讲的是 Ansible 安装与基本配置,主要包含以下内容: Ansible 环境准备 安装 Ansible 配置运行环境 Ansible 环境准备 从 GitHub ...

  5. Kubernetes master无法加入etcd 集群解决方法

    背景:一台master磁盘爆了导致k8s服务故障,重启之后死活kubelet起不来,于是老哥就想把它给reset掉重新join,接着出现如下报错提示是说etcd集群健康检查未通过: error exe ...

  6. Windows下升级Zabbix Agent

    这段时间因工作上不太忙,就着手升级下zabbix,从3升级到最新版4.2,服务器端升级还挺快,就是客户端比较耗时了,往往就是看的越简单的东西越耗时间啊. Windows版本的zabbix agent下 ...

  7. TypeScript模块系统、命名空间、声明合并

    命名空间 命名空间能有效避免全局污染.在ES6引入模块之后,命名空间就较少被提及了.如果使用了全局的类库,命名空间仍是一个好的解决方案. namespace Shape{ const pi = Mat ...

  8. SpringBoot 2 快速整合 | Hibernate Validator 数据校验

    概述 在开发RESTFull API 和普通的表单提交都需要对用户提交的数据进行校验,例如:用户姓名不能为空,年龄必须大于0 等等.这里我们主要说的是后台的校验,在 SpringBoot 中我们可以通 ...

  9. Unity3D_10_文件夹目录架构

    一:几个特殊文件夹介绍 1.Editor Editor文件夹可以在根目录下,也可以在子目录里,只要名子叫Editor就可以.比如目录:/xxx/xxx/Editor 和 /Editor 是一样的,无论 ...

  10. WInform中实现设置ZedGraph中曲线的X轴与Y轴的上限与下限

    场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...