故事背景

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

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

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 85D Sum of Medians Splay | 线段树

    Sum of Medians 题解: 对于这个题目,先想到是建立5棵Splay,然后每次更新把后面一段区间的树切下来,然后再转圈圈把切下来的树和别的树合并. 但是感觉写起来太麻烦就放弃了. 建立5棵线 ...

  2. bzoj 1588: [HNOI2002]营业额统计(splay入门)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588 题解:这题如果用普通的bst的话是可以过时间差不多4s左右如果用splay的话是14 ...

  3. poj3984 迷宫问题(简单的输出路径的bfs)

    题目链接 http://poj.org/problem?id=3984 中文题题意不解释了 反正就是简单的结构体套结构体存一下路径就行了 #include <iostream> #incl ...

  4. icpc 江苏 D Persona5 组合数学 大数阶乘(分段阶乘) 大数阶乘模板

    Persona5 is a famous video game. In the game, you are going to build relationship with your friends. ...

  5. hdu 2844 Coins 多重背包(模板) *

    Coins                                                                             Time Limit: 2000/1 ...

  6. Ubuntu18.04双系统下安装CUDA10+cuDNN7.5

    前言 本篇写于2019-4-25 这两天装Ubuntu18.04双系统简直装到崩溃.一是非常著名的开机卡死在Logo界面的问题,另一个是在装Nvidia驱动和CUDA的时候,更是费心.而网上的资料又良 ...

  7. Erlang模块gen_tcp翻译

    概述 TCP/IP套接字接口 描述 gen_tcp模块提供了使用TCP / IP协议与套接字进行通信的功能. 以下代码片段提供了一个客户端连接到端口5678的服务器的简单示例,传输一个二进制文件并关闭 ...

  8. javascript合并两个数组

    在开发的过程中,我们很多时候会遇到需要将两个数组合并成一个数组的情况出现. var arr1 = [1, 2, 3]; var arr2 = [4, 5, 6]; // 将arr1和arr2合并成为[ ...

  9. Django2.* + Mysql5.7开发环境整合

    环境: MAC_OS 10.12 python 3.6 mysql 5.7.25 django 2.2.3 前提:python django mysql都已经安装成功可单独运行 一.settings中 ...

  10. 爬取凤凰网站财经类的新闻,函数时编程,可全部实现,由于内容量大,需要时间太长,服务器会禁止,为了防止,可以将time.sleep()设置的时间长点

    import requests from selenium import webdriver import time def grasp(urlT): driver = webdriver.Chrom ...