先看代码
class People {
    int i;
    People(int ii) {
        i = ii;
        System.out.println(i);
    }
}public class FinalTest {
    private final int i = 1;
    private final int j;
    private final People p;
    public FinalTest() {
        j = 2;   //问题在这,被final修饰的变量不是常量吗?不是不能改变吗?
        p = new People(3);
        System.out.println(j);
    }
    public FinalTest(int x) {
        j = x;
        p = new People(x);
        System.out.println(j);
    }
    public static void main(String[] args) {
        FinalTest ft = new FinalTest();
        FinalTest ft1 = new FinalTest(4);
    }
}在这个代码中,不管是被final修饰的基本数据类型还是引用似乎都可以改变,高手来解释!
此程序可以编译通过,并能正确运行。

解决方案 »

  1.   

    final意思是仅可被赋值一次。
      

  2.   

    j = 2;  //问题在这,被final修饰的变量不是常量吗?不是不能改变吗?
    如果你这里都不赋值,连编译都过不了,好好想想为什么吧.
      

  3.   

    private final int j; 只是一个声明而已j=2才是赋值
      

  4.   

    final 表示被赋值后不能再改变。
      

  5.   

    final的变量可以再声明的时候或者在构造的时候赋值,且只能在这两个地方赋值,LZ的程序没有什么问题啊,分别得在构造方法里对变量赋值
      

  6.   

    补充一下:
    对于final修饰的引用,只是引用不能再指向其他对象,但其所指对象的属性还是可以被修改的.
      

  7.   

    我欲晕倒,final要不就是声明时就立即显式赋值,
    要不就是在构造函数中显示赋值(当然此时它是成员变量。)
      

  8.   

    楼主定义了私有最终不能修改的成员变量j,分别在不同的构造方法进行赋值
    ft和ft1两个引用操作的j算是第一次赋值,final 表示被赋值后不能再改变
      

  9.   

        private final int i;
        public static void main(String[] args) { 
            System.out.println(i);
            i=2;//你试试
             System.out.println(i);
        } 
      

  10.   

    1.final修饰的基本类型变量必须赋值,但是只能赋值一次(可以在声明时显示初始化赋值,或者在构造方法中初始化赋值,或者在初始化块中初始化赋值)。
      你在声明时: private final int j; 没有显示初始化,那么就必须在构造方法中初始化赋值,或者在初始化块中初始化赋值,否则编译时出错,正因为你在构造方法里面:j=2;给j赋值了,所以编译通过;你把j=2注释掉,试一下就知道了;
    2.final修饰的引用类型变量赋值之后,不能再指向其他对象!但是所引用对象的内部属性的值是可以改变的。
      

  11.   

    就是的 前边的定义是声名一个final变量 后边的是赋值 并没有再次赋值
      

  12.   


       public FinalTest() { //构造方法
            j = 2;  //问题在这,被final修饰的变量不是常量吗?不是不能改变吗? 
            p = new People(3); 
            System.out.println(j); 
        } 
        public FinalTest(int x) { //(有参)构造方法
            j = x; 
            p = new People(x); 
            System.out.println(j); 
        } 
    final必须在构造方法结束之前被赋值。可以在构造方法前面,也可以在构造方法中。
    LZ,请问你还能在别的地方把j的值改变吗。
      

  13.   

    我在书上看到过,这叫做空白final,是为了让程序更具灵活性而设计的。
    在未给予初始化值的情况下,可以在以后给final变量赋一次值,但这次赋完值之后就不能改动了。
      

  14.   

    LZ不能纠结能不能变的,有的情况final是能变的
      

  15.   

    不是,还有问题,就是我在第一个构造函数里对j赋了初值2,然后我在第二个构造函数里又令j=x;
    按你们的意思这里是重新初始化了,但之前然不成对j赋值了2没有成功?前面我知道意思了,关键是要解释下这一点,还有我用debug测试了下程序,j会默认初始化为0,然后它的值再改变为2,然后改变为3.   请哪位大侠用myeclipse去debug一下。然后帮我解释一下啊。
      

  16.   

    final修饰成员变量的话 表示这个变量只能被赋值一次
      

  17.   

    楼主是不是很没把类的构造函数搞清楚? FinalTest ft = new FinalTest(); 
     FinalTest ft1 = new FinalTest(4);这分别是实例化了2个FinalTest类 
    虽然都是FinalTest 但是是两个不同的内存块另外在第一个不带参数的构造函数中 p=new People(3);
    这里需要搞清楚People类里面有个i变量
    在FinalTest类中你也定义了一个i
    但是这两个i其实是不一样的两个变量
    对应的是两个不同的内存地址
      

  18.   

    《thinking  in  java 4th 》262~274页   中文版的在141~147页,讲的非常清楚了 
      

  19.   

    http://blog.csdn.net/yubangqi/archive/2009/09/11/4541251.aspx
      

  20.   

    final的意思是只能被初始化一次
      

  21.   


    我对i没有疑问,就是对j有疑问,我用debug跑的时候j的赋值情况是0-->2-->0-->4
    意思就是说j的值在构造函数已经由0变成2了,既然它要在构造函数里初始化,为什么还会事先初始化为0呢?不懂!!!
      

  22.   

    如果final修饰的是局部变量,以初始化就不能改变了,如果修饰的是全局变量就不一样了
      

  23.   


    数据类型都是继承了object类 所以数据类型也是类 他也有属性方法等 如 string s, 变量s有length属性,有trim方法等 所以数据类型也有构造函数
    在定义变量的时候 数据类型自带的构造器或者说构造函数会预先给变量一个默认值 int默认值为0,string的默认值为null
    楼主可以这样理解:定义一个变量其实就是在实例化一种数据类型 
      

  24.   

    归根结底就是在声明j时,还没有分配内存,在构造函数中j=2 才是正正给它分配了内存,并且初始化为9。所以并没有违背,被final 修饰的变量,只能赋值一次且不可变的原则
      

  25.   

    楼主是标题党.......
      楼主是知道答案的,O(∩_∩)O哈哈~   把普通问题刻意敏感化。
         这个问题都不知道还怎么学java呀
          这是最基本的了(⊙o⊙)哦
      

  26.   

    首先掌握的是规则,java编程规范里很清楚,,
      

  27.   

    结帖了我也回一回吧!别人可能会看到。
    刚看了书明白了其中道理final的变量是一定要赋值的,但是这个赋值的时间是在构造对象时。
    也就是new 之后 final int j;  一定要有值。之后j不可以再被改变。当然如果你new两个对象就有两个j了。而不是改变原来的jclass test1 
    {
    final int i;//在构造对象之后必须已对常量初始化
    public static void main(String[] args) 
    {
    test1 t = new test1(123);
    test1 tt = new test1(12);
    }
    public test1(int i){
    this.i = i;
    System.out.println(i);
    }
    }
      

  28.   

    final的意思是只能被初始化一次