Java Strings微妙的差异

class Test { public static void main() { String s1 = null + null; //shows compile time error String s1 = null; String s2 = s1 + null; //runs fine } } 

任何人都可以解释一下这种行为的原因吗?

这段代码:

 String s1 = null + null; 

尝试对两个null执行加法运算,这是无效的。

在这里:

 String s1 = null; String s2 = s1 + null; 

您为s1指定了null 。 然后执行s1null连接。 s1的类型是String ,因此根据字符串转换规则, s1 + null将转换为"null"字符串,如JLS§15.1.11 – 字符串转换:

如果引用为null,则将其转换为字符串"null" (四个ASCII字符n, u, l, l )。

否则,执行转换就好像通过调用没有参数的引用对象的toString方法一样; 但是如果调用toString方法的结果为null ,则使用字符串"null"

并且将连接为 – s1 + "null";

+运算符作为String连接仅在一个(或两个)操作数具有String类型时适用。

这在Java语言规范中定义

如果+运算符的任一操作数的类型String ,则操作是字符串连接。

 String s1 = null + null; //shows compile time error 

操作数具有null类型,即。 不是String ,所以不会发生字符串连接。 Java然后认为你正在做一个添加,它也不适用于null类型。

 String s2 = s1 + null; //runs fine 

s2具有String类型,即使它引用null ,因此可以发生字符串连接。

在下面的情况下,您正在对两个null执行操作,并且没有为两个null定义+操作。

 String s1 = null + null; 

在这一个中,您正在执行Stringnull串联。

 String s2 = s1 + null; 

另一个有趣的案例是,

 String abcd = (String) null + null; 

这将导致“nullnull”字符串,因为您将Stringnull并再次执行连接。 所以第一个null将被视为String

来自Javadoc :

Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。 字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的

因此,至少左操作数不能为null,因为StringBuffer.append(Object object)接受Object (包括null )作为参数。

基本上这是因为您正在处理文字,因此,COMPILER正在尝试对这些文字值执行操作。 它发生在编译时,并且与两个空值无关。

您获得的编译器错误等同于exception – 编译器不知道如何处理它,因此它会出错并给类型一个解释说它不起作用。