黑马程序员技术交流社区

标题: 关于final修饰变量及其初始化的一点疑问 [打印本页]

作者: 段海涛    时间: 2012-11-21 22:31
标题: 关于final修饰变量及其初始化的一点疑问
本帖最后由 段海涛 于 2012-11-22 09:38 编辑

1、这样写编译不能通过
  1. int x = 100;
  2. int y;
  3. if(x > 30) {
  4. y = -1;
  5. }

  6. System.out.println(y);
复制代码
2、这样写则编译能通过
  1. final int x = 100;
  2. int y;
  3. if(x > 30) {
  4. y = -1;
  5. }
  6. System.out.println(y);
复制代码
3、而这样写又不能通过
  1. final int x;
  2. x = 100;
  3. int y;
  4. if(x > 30) {
  5. y = -1;
  6. }
  7. System.out.println(y);
复制代码
请大神解答其中奥妙,为何第3种写法也不能通过编译呢?它和第2种写法的本质区别在哪里?






作者: jerry2627    时间: 2012-11-21 23:09
final修饰的变量只能初始化一次。
int x = 100;
int y;
if(x > 30) {
y = -1;
}

System.out.println(y);
这样Java虚拟机会认为y不一定能够被初始化到,所以编译错误。

加上final后,x的值就恒为100了,它就认为y一定会被赋值,所以能通过。

final int x;
x = 100;
int y;
if(x > 30) {
y = -1;
}
System.out.println(y);
final修饰的变量只能一次性完成赋值,否则报错。
作者: 张硕    时间: 2012-11-21 23:19
1 final修饰的局部变量
使用final修饰的局部变量就是只能被赋值一次!
其实它就是常量了!

2 final修饰的属性
final修饰的属性,必须在构造器结束之前完成赋值,而且只能被赋值一次!
当一个类有多个构造器时,如果其中某一个构造器没有对final属性赋值,那么就出错!
如果可能出现对final属性多次赋值那也出错!
final的属性没有默认值!因为他只能被赋值一次!


作者: 森仔    时间: 2012-11-22 00:11
本人理解如下,第一个若将代码改为:
int x = 100;
int y;
if(x > 30) {
y = -1;
System.out.println(y);
}
则可编译通过,说明y只是在if语块内被赋值的,是局部变量。上面那例子相当于
int y;  System.out.println(y);  木有给变量赋值引起的错误。
而 第二个例子能通过,是因为finall修饰变量后,该变量相当于常量了,例子就相当于
int y;
if(true){
y= -1;

System.out.println(y);  所以就通过了

至于第三个例子  改为
final int x;
x = 100;
int y;
System.out.println(x);
if(x > 30) {
        System.out.println("y");
y = -1;
}
System.out.println("y");
        }
后 执行的结果为
100
y
y
说明和第一个例子一样,同样y是if语块里的局部变量!
虽然finall 将x修饰定义成常量,可后来 x=100;又将其覆盖定义成了变量,这就和第一个例子一模一样了

作者: 倪鹏博    时间: 2012-11-22 00:19
第一段代码不能通过,是由于y可能没有被初始化,没有初始化不可以被输出语句使用!加上else语句,else之中再对y进行赋值的话,编译可以通过,说明编译器可以知晓判断语句的结果!大家的表述也很清楚;

第二段代码能通过的原因在于,final修饰x之后,x就代表常量100!编译器对常量的处理:在编译时,直接用常量值替代常量符号!所以第二段代码的判断语句在编译时期相当于:
  1. if(100 > 30) {
  2. y = -1;
  3. }
复制代码
所以编译时,y肯定是被初始化过的,所以编译可以通过!

第三段代码不能通过!其实是编译器没办法确定x做为常量的常量值而造成的!
第三段代码其实跟下面代码的效果完全相同
  1. final int x;
  2. int y,z=100;
  3. x = z;
  4. if(x > 30) {
  5. y = -1;
  6. }
  7. System.out.println(y);
复制代码
也就是x作为常量但是常量值不确定,所以判断语句的执行结果不确定,y也存在没有被初始化的可能!
导致编译不能通过!
作者: 段海涛    时间: 2012-11-22 08:22
倪鹏博 发表于 2012-11-22 00:19
第一段代码不能通过,是由于y可能没有被初始化,没有初始化不可以被输出语句使用!加上else语句,else之中 ...

解释很给力!赞一个!
作者: 黑马吕世成    时间: 2012-11-22 11:03
这个问题记住一点就是:无论什么情况下都能保证局部变量在使用前已经给它赋了初值。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2