您的位置:首页 > 编程语言 > Java开发

从头认识java-6.6 final(2)-属性域

2015-11-03 11:44 441 查看
接着上一章节的内容。

昨天我回去想了一下,发觉最后的那个特性还是有点问题,我就做了以下的实验。

昨天最后一点属性的简化版:

package com.ray.ch06;

public class Test {
private final String name = "abcd";

public String getName() {
return name;
}

public static void main(String[] args) {
Test test1 = new Test();
Test test2 = new Test();
System.out.println(test1.getName() == test2.getName());
}
}

输出:

true

但是,我通过另外一种形式改造一下代码:

package com.ray.ch06;

public class Test {
private final String name = new String("abcd");//改动的地方

public String getName() {
return name;
}

public static void main(String[] args) {
Test test1 = new Test();
Test test2 = new Test();
System.out.println(test1.getName() == test2.getName());
}
}


输出:

false

为什么?

我查找了一些资料,发现,上面的这种情况是编译器的优化机制,编译器对于常量字符串是优化的,但是对于new String这种字符串,没有做出优化,因此,就会出现上面的这两种情况。

参考文章:

java编译器对字符串+运算的优化导致的有趣现象

Java编译器中对String对象的优化

下面我们开始今天的章节。(4)final的属性域必须在对象初始化前就已经初始化。

也就是,final的属性域必须在new前就已经初始化

下面是两种初始化方法:

package com.ray.ch06;

public class Test {
private final int id;
private final String name;

{
id = 0;
}

public Test() {
name = "abcd";
}

}

final属性域要么在构造器里面初始化,要么在代码块里面初始化,如果不初始化,则编译器抛异常。

因为无论是代码块,还是构造器,都在new之前执行的。

而且,上面使用了空白final属性域,使得这个属性可以在运行时赋值,增加代码的灵活性,还有,一旦初始化了final属性域,它就不能改变值或者引用(这里可以回头看上一章节)。

(5)作为参数的时候,无法改变指向的对象。

package com.ray.ch06;

public class Test {
private void say(final Value value) {
// value = new Value();//error
}
}

class Value {
}

代码里面的new是错误的。

总结:这一章节主要讲述了编译器对于string 的优化,以及final属性域的两个注意点。

这一章节就到这里,谢谢。

-----------------------------------

目录
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: