final修饰的变量可以被改变了?高手来看看

bb100044535 2009-09-10 05:28:22
先看代码
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修饰的基本数据类型还是引用似乎都可以改变,高手来解释!
此程序可以编译通过,并能正确运行。
...全文
1342 38 打赏 收藏 转发到动态 举报
写回复
用AI写文章
38 条回复
切换为时间正序
请发表友善的回复…
发表回复
heyouli 2010-08-11
  • 打赏
  • 举报
回复
final的意思是只能被初始化一次
coooliang 2010-07-03
  • 打赏
  • 举报
回复
结帖了我也回一回吧!别人可能会看到。
刚看了书明白了其中道理

final的变量是一定要赋值的,但是这个赋值的时间是在构造对象时。
也就是new 之后 final int j; 一定要有值。之后j不可以再被改变。

当然如果你new两个对象就有两个j了。而不是改变原来的j

class 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);
}
}
zhangyong20081204 2009-09-13
  • 打赏
  • 举报
回复
首先掌握的是规则,java编程规范里很清楚,,
m_angle_m 2009-09-13
  • 打赏
  • 举报
回复
............................
TzSword 2009-09-13
  • 打赏
  • 举报
回复
楼主是标题党.......
楼主是知道答案的,O(∩_∩)O哈哈~

把普通问题刻意敏感化。。。。
这个问题都不知道还怎么学java呀
这是最基本的了(⊙o⊙)哦
maxwellno1 2009-09-12
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 bb100044535 的回复:]
我对i没有疑问,就是对j有疑问,我用debug跑的时候j的赋值情况是0-->2-->0-->4
意思就是说j的值在构造函数已经由0变成2了,既然它要在构造函数里初始化,为什么还会事先初始化为0呢?不懂!!!
[/Quote]

数据类型都是继承了object类 所以数据类型也是类 他也有属性方法等 如 string s, 变量s有length属性,有trim方法等 所以数据类型也有构造函数
在定义变量的时候 数据类型自带的构造器或者说构造函数会预先给变量一个默认值 int默认值为0,string的默认值为null
楼主可以这样理解:定义一个变量其实就是在实例化一种数据类型
dichyzhu 2009-09-12
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 zhen987 的回复:]
1.final修饰的基本类型变量必须赋值,但是只能赋值一次(可以在声明时显示初始化赋值,或者在构造方法中初始化赋值,或者在初始化块中初始化赋值)。
  你在声明时: private final int j; 没有显示初始化,那么就必须在构造方法中初始化赋值,或者在初始化块中初始化赋值,否则编译时出错,正因为你在构造方法里面:j=2;给j赋值了,所以编译通过;你把j=2注释掉,试一下就知道了;
2.final修饰的引用类型变量赋值之后,不能再指向其他对象!但是所引用对象的内部属性的值是可以改变的。
[/Quote]
精辟。
chenlly99 2009-09-12
  • 打赏
  • 举报
回复
归根结底就是在声明j时,还没有分配内存,在构造函数中j=2 才是正正给它分配了内存,并且初始化为9。所以并没有违背,被final 修饰的变量,只能赋值一次且不可变的原则
governlee 2009-09-11
  • 打赏
  • 举报
回复
楼上说得很对!不过你的问题还是很不错的~
chenlly99 2009-09-11
  • 打赏
  • 举报
回复
只能被赋值一次, j = 2; 正是第一次被赋值了。如果再在后面加入 j=10肯定就不行了
bb100044535 2009-09-11
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 maxwellno1 的回复:]
引用 18 楼 bb100044535 的回复:
不是,还有问题,就是我在第一个构造函数里对j赋了初值2,然后我在第二个构造函数里又令j=x;
按你们的意思这里是重新初始化了,但之前然不成对j赋值了2没有成功?前面我知道意思了,关键是要解释下这一点,还有我用debug测试了下程序,j会默认初始化为0,然后它的值再改变为2,然后改变为3.  请哪位大侠用myeclipse去debug一下。然后帮我解释一下啊。



楼主是不是很没把类的构造函数搞清楚?

FinalTest ft = new FinalTest();
FinalTest ft1 = new FinalTest(4);

这分别是实例化了2个FinalTest类
虽然都是FinalTest 但是是两个不同的内存块

另外在第一个不带参数的构造函数中 p=new People(3);
这里需要搞清楚People类里面有个i变量
在FinalTest类中你也定义了一个i
但是这两个i其实是不一样的两个变量
对应的是两个不同的内存地址


[/Quote]

我对i没有疑问,就是对j有疑问,我用debug跑的时候j的赋值情况是0-->2-->0-->4
意思就是说j的值在构造函数已经由0变成2了,既然它要在构造函数里初始化,为什么还会事先初始化为0呢?不懂!!!
ctlu2ct2t 2009-09-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 zhen987 的回复:]
1.final修饰的基本类型变量必须赋值,但是只能赋值一次(可以在声明时显示初始化赋值,或者在构造方法中初始化赋值,或者在初始化块中初始化赋值)。
  你在声明时: private final int j; 没有显示初始化,那么就必须在构造方法中初始化赋值,或者在初始化块中初始化赋值,否则编译时出错,正因为你在构造方法里面:j=2;给j赋值了,所以编译通过;你把j=2注释掉,试一下就知道了;
2.final修饰的引用类型变量赋值之后,不能再指向其他对象!但是所引用对象的内部属性的值是可以改变的。
[/Quote]

顶这个!
justinavril 2009-09-11
  • 打赏
  • 举报
回复
final的意思是只能被初始化一次
tfsict2008 2009-09-11
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 bb100044535 的回复:]
不是,还有问题,就是我在第一个构造函数里对j赋了初值2,然后我在第二个构造函数里又令j=x;
按你们的意思这里是重新初始化了,但之前然不成对j赋值了2没有成功?前面我知道意思了,关键是要解释下这一点,还有我用debug测试了下程序,j会默认初始化为0,然后它的值再改变为2,然后改变为3.  请哪位大侠用myeclipse去debug一下。然后帮我解释一下啊。
[/Quote]
j会默认初始化为0这个你要想搞明白的话,你去看看虚拟机规范,这个不属于程序员的行为。
然后它的值再改变为2,然后改变为3这个干本就不是先变成2再改变为3的问题,
是本来就是2和本来就是3的问题
yubangqi 2009-09-11
  • 打赏
  • 举报
回复
《thinking in java 4th 》262~274页 中文版的在141~147页,讲的非常清楚了
zhoulin_062 2009-09-11
  • 打赏
  • 举报
回复
如果final修饰的是局部变量,以初始化就不能改变了,如果修饰的是全局变量就不一样了
maxwellno1 2009-09-10
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 bb100044535 的回复:]
不是,还有问题,就是我在第一个构造函数里对j赋了初值2,然后我在第二个构造函数里又令j=x;
按你们的意思这里是重新初始化了,但之前然不成对j赋值了2没有成功?前面我知道意思了,关键是要解释下这一点,还有我用debug测试了下程序,j会默认初始化为0,然后它的值再改变为2,然后改变为3.  请哪位大侠用myeclipse去debug一下。然后帮我解释一下啊。
[/Quote]


楼主是不是很没把类的构造函数搞清楚?

FinalTest ft = new FinalTest();
FinalTest ft1 = new FinalTest(4);

这分别是实例化了2个FinalTest类
虽然都是FinalTest 但是是两个不同的内存块

另外在第一个不带参数的构造函数中 p=new People(3);
这里需要搞清楚People类里面有个i变量
在FinalTest类中你也定义了一个i
但是这两个i其实是不一样的两个变量
对应的是两个不同的内存地址

haojia0716 2009-09-10
  • 打赏
  • 举报
回复
final修饰成员变量的话 表示这个变量只能被赋值一次
bb100044535 2009-09-10
  • 打赏
  • 举报
回复
不是,还有问题,就是我在第一个构造函数里对j赋了初值2,然后我在第二个构造函数里又令j=x;
按你们的意思这里是重新初始化了,但之前然不成对j赋值了2没有成功?前面我知道意思了,关键是要解释下这一点,还有我用debug测试了下程序,j会默认初始化为0,然后它的值再改变为2,然后改变为3. 请哪位大侠用myeclipse去debug一下。然后帮我解释一下啊。
加载更多回复(17)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧