以下代码将无法编译,因为编译器无法保证数据字段f
将被初始化。你是如何解决这个问题的?
import java.util.Scanner;
public class Foo
{
private final int f;
/*constructor*/
public Foo()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
if(i == 5)
f = sc.nextInt();//error: variable f might be assigned in a loop
}
}
public Foo(int i)
{
j = i;//no problem
}
}
这不是语言中的一个小故障,因为在我的其他构造函数中,我可以将f
设置为final
,并且因为它不是在循环中完成的。我知道编译器(愚蠢)看到一个循环并认为f
将被重新分配,但程序中的逻辑确保它只发生一次。这是Java如何“保护”程序员的一个例子吗?
对于每个人都想知道为什么f
被宣布为最终的Netbeans建议它,大概是当代码有很大不同时。
答案 0 :(得分:2)
private final int f;
↑
删除final
关键字。编译器不知道if
只会满足一次,并且您会在尝试多次更改f
时遇到错误:
可能已经指定了最终字段f
答案 1 :(得分:1)
首先,final字段是您无法更改分配给的值的字段。在您的每个循环移动的情况下,您更改该值,因此无法编译。删除f之前的最后一个单词。
public class Foo
{
private int f;
/*constructor*/
public Foo()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
if(i == 5)
f = sc.nextInt();
}
}
}
答案 2 :(得分:1)
你......不。
我知道编译器(是哑的)看到一个循环并认为f将被重新分配,但程序中的逻辑确保它只发生一次。这是Java如何“保护”程序员的一个例子吗?
这种行为,无论是否“保护”程序员,都是Java语言定义的结果(根据JLS)以及编译器如何正确执行语言规范。
最终变量只能分配给一次.. 如果分配了最终变量,那么这是一个编译时错误,除非在分配之前它是明确未分配的(§16)。
请参阅Chapter 16. Definite Assignment,其中详细讨论了此有限静态分析案例的规则。
答案 3 :(得分:0)
private final int f;
您使用final作为声明,这将不允许为f
重新分配另一个值最终变量只能通过一个初始化一次 初始化程序或赋值语句。
详细了解最终here
所以只需使用
private int f;
答案 4 :(得分:0)
当你将任何变量声明为final时,不应该更改该值的值。那么是否需要将变量声明为final?
答案 5 :(得分:0)
这是catch,你可以在同一个地方或构造函数内部初始化任何最终实例,但不能初始化内部方法(METHOD)。
所以你会说我在构造函数中初始化!!但问题是你在for循环中多次更改最终实例变量的值,编译器会识别并抛出编译器错误。
编译内联最终代码,如下所示。
private final int f = 10 //even if you initialize it inside the constructor only one time.
离
public class Foo {
private final int f; // byte code becomes 'private final int f = 10' for each instance
Foo() {
f = 10;
}
}