Puzzle 16: Line Printer
分行符导致的问题
看看下面这段代码:
public class LinePrinter {
public static void main(String[] args) {
// Note: \u000A is Unicode representation of linefeed(LF)
char c = 0x000A;
System.out.println(c);
}
}
这里说明一下, Unix-like系统的分行符是LF, 而windows系统中的分行符是CR+LF... … , 你也许还在思考这段代码是否具有平台相关性. 但在NetBeans中, 已经告诉你这段程序无法通过编译. 嗯, 这也是平台独立-- 在任何平台下都不能通过编译. 不过, NetBeans的提示信息是在是让人不知道问题在哪里—机器到底还是笨啊.
前面的Puzzle 14提到Java编译器在解析之前要将Unicode转义字符替换成它所表达的字符. \u000A 被替换成了一个不可见字符–换行符, 以上程序实际上等价于:
public class LinePrinter {
public static void main(String[] args) {
// Note:
is Unicode representation of linefeed(LF)
char c = 0x000A;
System.out.println(c);
}
}
“is Unicode representation of linefeed(LF)” 这段话不是注释, 而成了程序正文的一部分, 当然要报错了.注: 替换Unicode转义字符成相关字符的操作会发生在丢弃空白和换行符之前.
最简单的解决办法就是删掉这句注释了. 另外根据JLS 3.10.6, 000A即是\n的Unicode, 所以以上代码中c可声明为如下形式, 含义更清楚:
- char c = '\n';
Puzzle 14, 15, 16 讲述了一些关于Unicode转义字符的问题, 这是一个容易引起迷惑之处, 能不用则不用.
其他:平台兼容问题
按照书中P37的说法, 当取消注释之后, 这个程序使能运行了, 但有平台相关的问题. 这个说法需要验证.
代码片段:
char c = 0x000A;
System.out.println("Start");
System.out.println(c);
System.out.println("End");
在windows上运行, 输出:
Start
End
中间是两个空行.
以上是Windows下编译的代码用于Windows平台, 根据编译平题和运行平台的不同,统计上段代码执行之后输出的空行数目如下表:
注: 假定编译好的代码, 整个目录存放在hello文件夹下, 路径为: hello/book/javapuzzlers/ch03/p16/LinePrinter, 则在控制台下切换到hello目录下, 执行java book.javapuzzlers.ch03.p16.LinePrinter 可查看到运行结果.
TODO 2:
如何打包class文件(制作jar文件), 通过Eclipse较为容易, 通过NetBeans呢? 手工呢?
附
- Puzzle 14: Escape Rout
- JLS 3.2 Lexical Translations
- JLS 3.4 Line Terminators