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呢? 手工呢?

  1. Puzzle 14: Escape Rout
  2. JLS 3.2 Lexical Translations
  3. JLS 3.4 Line Terminators