java in puzzles summary
第二章 Expressive Puzzles
第三章 with Character
Puzzle 11 The Last Laugh
执行下面的代码
1 | public class LastLaugh { |
预期的打印结果是
1 | HaHa |
但是实际情况如下
1 | Ha169 |
第二个打印语句实际上是将两个字符的ASCII码值相加的结果
下面的语句是可以将两个字符连起来的
1 | System.out.print(""+'H' + 'a'); |
下面的例子中 不会输出两个数字相加的结果,而是将数字相加的操作作为字符串打印出来
1 | System.out.println("2 + 2 = " + 2+2); |
从 Java1.5 开始,下面的语句也可以将 两个 char
,作为字符串链接输出
1 | System.out.printf("%c%c", 'H', 'a'); |
结论
the
+
operator performs string concatenation if and only if at least one of its operands is of type String; otherwise, it performs addition.当且仅当运算符中的至少一个是字符串类型时,
+
运算符才执行字符串连接,在其他情况下执行加操作
如果需要进行字符串连接的几个值之间没有一个是 String
类型,那么有以下几个选择:
- 增加一个空字符串
""
- 使用
String.valueOf()
进行显式转换; - 使用
StringBuffer
/StringBuilder
- 使用上面提到的
System.out.printf("%c%c", 'H', 'a');
的写法
Puzzle12 ABC
运行下面的代码
1 | String letters = "ABC"; |
预期输出
1 | ABC easy as 123 |
实际输出
1 | ABC easy as [C@5e2de80c |
之所以会出现上面的结果是因为 在打印的时候 numbers
调用了 Object
的 toString
方法:
1 | public String toString() { |
所以会导致 出现上面的字符串
为了解决上面的问题,可以调用 String.valueOf(char[] data)
方法,该方法会答应出字符数组内所有的字符:
1 | String letters = "ABC"; |
上面的代码输出
1 | ABC easy as 123 |
也可以使用下面的分开输出的方法
调用 println(char[] data)
方法:
1 | String letters = "ABC"; |
总结
char arrays are not strings. To convert a char array to astring, invoke String.valueOf(char[]) .char
数组不是字符串。 要将char数组转换为字符串,请调用String.valueOf(char [])。
Puzzle 14 Escape Rout
这里实际上是使用 Unicode 标识 ASCII 字符
1 | System.out.println("a\u0022.length() + \u0022b".length()); |
打印结果是 2
等同于
1 | System.out.println("a".length() + "b".length()); |
使用转义之后,即可打印字符串的长度
1 | System.out.println("a\".length() + \"b".length()); |
结论
In summary, prefer escape sequences to Unicode escapes in string and character literals.
总之,相对于字符串和字符文字中的Unicode转义,更喜欢转义序列。
Do not use Unicode escapes to represent ASCII characters.
不要使用Unicode转义符表示ASCII字符。
Puzzle 20 What’s My Class?
下面的代码是将字符串中的所有点号转换成斜杠
1 | public static void main(String[] args) { |
最后打印的结果是
1 | com.bruceliu.algorithms.puzzles.MyTest |
出现这个结果的原因是 replaceAll()
方法的第一个参数是一个正则表达式
(regular expression
),而不是一个字符串序列
正则表达式“。” 匹配任何单个字符,因此类名的每个字符都用斜杠替换,产生我们看到的输出。
1 | public static void main(String[] args) { |
自 JAVA 1.5
开始,也可以使用以下代码
1 | System.out.println(MyTest.class.getName(). |
要仅匹配句点字符,正则表达式中的句点必须通过在其前面加上反斜杠(\)进行转义。 因为反斜杠字符在字符串文字中有特殊含义-它开始一个转义序列-后面的斜杠本身必须用第二个反斜杠转义。
Puzzle: 21
执行下面的代码
1 | System.out.println(MeToo.class.getName().replaceAll("\\.", File.separator) + ".class"); |
这段代码在 windows
平台会报错
File.separator
在 windows
平台是反斜杠 backslash
,反斜杠会对其之后的字符进行转义。而在上面的例子中,反斜杠后面没有其他字符了,所以第二个参数是一个无效的输入。
自 java 1.5
之后有两种方法解决这个问题,方法一:
1 | System.out.println(MyTest.class.getName().replaceAll("\\.", Matcher.quoteReplacement(File.separator))+ ".class"); |
方法二:
1 | System.out.println(MyTest.class.getName().replace(".", File.separator) + ".class"); |
在 java 1.5
之前同样也有解决方法
1 | System.out.println(MyTest.class.getName().replace('.', File.separatorChar) + ".class"); |
Puzzle: 23 No Pain,No Gain.
1 | import java.util.Random; |
有如下三个bug
- rnd.nextInt(2) 的取值范围是[0,2),2是永远不可能取到的,这里应该改成 rnd.nexInt(3);
switch
语句没有break
,应该给每一个分支增加 break;new StringBuffer(char)
实际调用的是new StringBuffer(int capacity)
,即给StringBuffer
初始化大小,并不是new StingBuffer(String str)
初始化字符串
可以进行如下的修改
1 | import java.util.Random; |
这个代码还可以写得更加优雅
1 | System.out.println("PGM".charAt(rnd.nextInt(3)) + "ain"); |
第四章 Loopy Puzzlers
Puzzle 24: A Big Delight in Every Byte
java in puzzles summary
install_url
to use ShareThis. Please set it in _config.yml
.