如何编译没有错误?根据我的理解,编译器会检查变量的类型(在本例中为String
),然后查看右侧表达式的类型是否与变量的类型(或至少是一个子类型)相对应但是,让我们坚持String
类的简单案例,因为它是最终的。
public class InitClass {
public static void main(String[] args) {
String str = (str = "hello");
System.out.println(str);
}
}
我的问题是str = "hello"
如何编译?编译器是否已经知道str
的类型应为String
?
答案 0 :(得分:15)
首先,评估左侧操作数以生成变量。 If 此评估突然完成,然后是赋值表达式 因同样的原因突然完成;右手操作数不是 评估并且没有分配。
产生变量str
。然后
否则,评估右侧操作数。如果这个评价 突然完成,然后赋值表达式突然完成 出于同样的原因,没有任何转让。
在您的示例中,右侧操作数本身是另一个赋值表达式。因此,str
,赋值运算符的右手操作数,再次被计算以生成变量str
。然后
否则,右侧操作数的值将转换为 左侧变量的类型,进行值集转换 (§5.1.13)到适当的标准值集(不是 扩展指数值集),和转换结果 存储在变量中。
因此"hello"
存储在str
中。 And since
在运行时,赋值表达式的结果是值 分配发生后的变量。一个结果 赋值表达式本身不是变量。
将"hello"
分配给str
的结果是值"hello"
,该值再次存储在str
中。
答案 1 :(得分:5)
您的情况相当于
String str;
str = (str = "hello");
虽然作业看起来很滑稽,但从概念上来说并没有错。
然而,引用自身的变量初始化显然不是一个好主意。编译器将尝试在很可能是程序错误的情况下标记它;编译器有时无法这样做;并且可能还会在其他时间过火。
局部变量具有更严格的要求(比字段变量更大) - 必须在使用其值之前先分配它。例如,这不会编译,因为本地var在被分配之前被读取。
String str; // local variable
str = str; // error, try to read `str` before it's assigned
字段变量始终具有默认初始值;尽管如此,编译器会检查明显的程序错误
int x = x+1; // error. x is field variable.
但如果此类检查失败,那么这不是灾难性的,因为x
在明确分配之前具有值0
int x;
{ x=x+1; } // ok. x==0, then x==1 after assignment
但是,如果x
为final
,则上述代码失败,因为编译器在读取x
之前需要先明确赋值x
,对局部变量的要求相同。但是这种检查可以被规避,因为它不可能完全分析并完全阻止它用于场变量
final int x = (this).x+1; // compiles!
在某些情况下,编译器过分,阻止涉及lambda的合法用例
Runnable r1 = ()->System.out.println(r1); // r1 is a field variable
在这个用例中,概念上没有任何问题;它也可以被(this).
规避。
答案 2 :(得分:0)
首先发生的是编译器识别引用的类型然后知道这是一个字符串赋值"你好"到str是有效的。