按照作用域,final变量分为:
1.class范围的static final var;
2.instance范围的final var;
3.method范围的final var包含final parameters;
其中类级别的final在整个类的命名空间只有一个实例,instance final则每个对象都有各自final的实例,且可以各不相同,method中的final则针对每次调用有一个final变量。
如下代码所示:在每个ClassLoader 加载FinalVariable时classInt被初始化一次以后不会再改变;对于instanceInt,每次创建FinalVariable对象,各个对象包含的instanceInt可能各不相同;而methodInt则每次即使是相同对象的多次调用可能产生不同的int值。
class FinalVariable{
static final int classInt = new Random().nextInt();
final int instanceInt = new Random().nextInt();
public int getMethodInt() {
final int methodInt = new Random().nextInt();
return methodInt;
}
}
---------------------------------------------------------------------------------------------
final常量;
primitive和string类型如果是final的且该final常量由常量值直接赋值,则编译时会在引用处直接替换成对应的常量值。
Final Collections:
Java API Collections中提供了产生不可变集合的接口:
只要把Collection变量定义成final的,通过调用类似如上的接口进行赋值,就可以产生一个Immtable的集合了。
其缺点是当修改此集合时无法在编译时监测而要到运行时抛出异常。
Final Class:不能被继承的Class,有两只方式:
1.定义类时前面加上final;
2.将类的所有构造器都定义成private的。
Final Method:不能被子类重写的方法(注意可以被重载):
Java默认都是virtual method,C#默认不是virtual method的。C#会强制你去思考为什么要设计成virtual方法,感觉这样更合理。
条件编译:
利用编译器对常量的优化可以做出条件编译的效果:
class FinalTest{
private static final ISDEBUG= false;
public void getInteger(){
if(ISDEBUG){
debug.
}
}
}
Final关键字可以成为我们设计代码的一个有效工具。