例如我有以下代码
class Format{
public static void main(String[] args) {
String formated = String.format( "%c",-42); //I have -42 as second argument.
System.out.println(formated);
}
}
我知道这非常糟糕,因为它会抛出IllegalFormatCodePointException,但是我想到的问题是编译器为什么不在这里抱怨,如果它可以抱怨
char c = -42;
因此,知道上层代码会产生异常,为什么编译器只是坐着看?
答案 0 :(得分:2)
在语言层面没有设施来定义这种类型的约束。
编译器可以检查的是参数的类型是the method prototype定义的参数类型:
public static String format(String format, Object... args)
你可以看到它非常动态,有时候你可以传递一个int,有时甚至是其他东西,这很方便,特别是当一些format strings能够处理各种类型时。格式字符串本身也可以动态提供。
我不知道任何实现printf
的语言,并且能够静态检查。这是一个特殊的功能,它始终使用语言实现,而不是语言定义级别。
答案 1 :(得分:2)
因此,知道上面的代码会产生异常。为什么编译器只是坐着观看?
因为Java语言规范说它应该。
format
方法的类型签名是format(String format, Object... args)
,JLS表示如果在应用规定的转换后参数符合该签名,则代码有效。编译器 NOT ALLOWED 为您的代码说“编译错误”...因为代码是有效的Java代码。
事实上,编译器可能“知道”您的代码将始终产生异常的唯一方法是使用特殊的字符串格式来编码。而且,在这种情况下,具有该特殊知识的(假设的)编译器允许做的最多就是输出警告。
实际上,这种事情被视为超出了典型编译器的范围。相反,它是静态分析工具的问题领域,如FindBugs和PMD。 (或者对于C语言,Lint工具...... IIRC在某些版本中检查格式字符串。)