Java Final 总结

[b]final表示“不可变的”或“终态的”,可以用在类、方法、变量上。[/b]


[b]用在类上:[/b]表示该类不能被继承。
final不能用来修饰抽象类。原因显而易见:final类不能被继承,而抽象类应该被继承,这是矛盾的。
同理也不能用来修饰100%抽象的接口(interface)。

[b]用在方法上:[/b]表示该方法不能被子类重写。
final不能用来修饰抽象方法。原因显而易见:final方法不能被子类重写,而抽象方法应该被子类重写(或子类亦声明为抽象类)。

[b]用在变量上:[/b]表示该变量[b]只能被赋值一次(JLS Def:A final variable may only be assigned to once)[/b]。
因为只能赋值一次,所以一经赋值其[color=red][b]值[/b][/color]就不会再改变。
因为final变量"[b]值[/b]不可变",对引用类型:引用(变量)reference存储的值就是其所指向的对象实例的Heap中地址,那么该引用(变量)就始终指向同一个对象实例(注意不是该final变量指向的对象的属性不可变!)。
变量声明中不包含赋值操作的final变量称为blank final。
做了初始化的基本类型或String类型的final变量,称为constant variables。


[b]final成员变量有默认值(default value)吗?[/b]
成员变量如未初始化是有默认值的(编译器指定)([url]http://wuaner.iteye.com/admin/blogs/1666376[/url]),final成员变量也不例外。如下例:[quote]Src:[url]http://www.coderanch.com/t/241783/java-programmer-SCJP/certification/help-blank-final-variables[/url]

public class FinalFieldsDefaultValue {

final int someInt;
final String someStr;

{
System.out.println(getSomeInt());
System.out.println(getSomeStr());
}

int getSomeInt() {
return someInt;
}

String getSomeStr() {
return someStr;
}

FinalFieldsDefaultValue() {
someInt = 2;
someStr = "abc";
System.out.println(someInt);
System.out.println(someStr);
}

public static void main(String[] args) {
new FinalFieldsDefaultValue();
}

}
Output:
0
null
2
abc[/quote]
final成员变量存在默认值(说明编译器对其做了隐式的赋值操作),而我们又可以对其做一次(只能是一次)赋值操作,这似乎与JLS中final变量的定义(A final variable may only be assigned to once)矛盾,我们只能这样认为:JLS中final变量的定义不够严格,应该加上并着重强调[b][color=red]显式(explicitly/definitely)[/color][/b]二字:
[b][size=medium]A final variable may only be [color=red]explicitly[/color] assigned to once[/size][/b]


[b]final成员变量[color=red]必须[/color]显式赋值[/b]
正是因为final成员变量存在默认值,所以必须对其进行显式的赋值,否则编译无法通过。我想java正是通过这样的强制方式以防止你取到final成员变量的默认值(类似int-0、reference-null这样的默认值肯定不是你想要的,不是你声明“终态”final变量的初衷)。
对final成员变量的显式赋值操作可以是:
可以在声明变量时赋值;
类变量:还可以在静态初始化块(Static Initializers、Static Initialization Blocks)中赋值
实例变量:
1 还可以在实例初始化块(Instance Initializers、Instance Initialization Blocks)中赋值
2 还可以在构造方法中赋值(每一个存在(显式或隐式)super()调用的构造方法里都要做,即位于本类构造方法调用链链尾的构造方法里都要做,参考:[url]http://wuaner.iteye.com/blog/1669937[/url])[quote]JLS 3rd - 8.3.1.2 final Fields [url]http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.3.1.2[/url]
It is a compile-time error if a blank final (§4.12.4) class variable is not definitely assigned (§16.8) by a static initializer (§8.7) of the class in which it is declared.[b](final类变量如果既未在声明时赋值,也未在静态初始化块中赋值,报编译错误)[/b]
A blank final instance variable must be definitely assigned (§16.9) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs.[b](final实例变量如果未在声明时赋值,且在构造函数调用结束后未被显式赋值,报编译错误)[/b][/quote]


通常将final和static结合使用来实现java中的常量:
[url]http://wuaner.iteye.com/admin/blogs/1669122[/url]


Sources:
JLS 3rd - 4.12.4 final Variables
[b][url]http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.12.4[/url][/b]
JLS 3rd - 8.3.1.2 final Fields
[b][url]http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.3.1.2[/url][/b]
JLS 3rd - 17.5 Final Field Semantics
[b][url]http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5[/url][/b]
JLS 3rd - 13.4.9 final Fields and Constants
[b][url]http://docs.oracle.com/javase/specs/jls/se5.0/html/binaryComp.html#13.4.9[/url][/b]
Java Tutorials - Writing Final Classes and Methods
[url]http://docs.oracle.com/javase/tutorial/java/IandI/final.html[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值