今天使用java.util.Formatter发现一个小陷阱,测试代码如下
Formatter f = new Formatter(System.out);
String s = "Test format";
f.format("%10.4s\n", s);
f.close();
System.out.println("end");
控制台预期的输出是这样:
Test
end
可实际结果却是这样:
Test
看了下Formatter的源码才发现问题,问题原因在这个方法f.close();如果不调用编译器会提示“'f' is never closed”。
Formatter的构造方法如下:
public Formatter(PrintStream ps) {
this(Locale.getDefault(Locale.Category.FORMAT),
(Appendable)Objects.requireNonNull(ps));
}
/* Private constructors */
private Formatter(Locale l, Appendable a) {
this.a = a;
this.l = l;
this.zero = getZero(l);
}
可以看出传入的输出流的引用传递给了Formatter对象的成员变量a.
下面是close()方法:
public void close() {
if (a == null)
return;
try {
if (a instanceof Closeable)
((Closeable)a).close();
} catch (IOException ioe) {
lastException = ioe;
} finally {
a = null;
}
}
这个方法不仅把a持有的对象引用释放了(垃圾回收),还调用了a的close()方法,而out是System类的静态域,只有一个对象,所以悲剧了,之后System.out无效了。。