java final关键字通常指的是“无法改变的”,但有时候应用在不同地方会产生误解,下面详细介绍在三种情况下的final:
一 final 数据
1 当对常量运用final时表示该常量永不改变,我想这个就不用过多表述,在类中一般与关键字static一起使用。public static final int PI = 3.1215026 就是一个最典型的对常量进行定义的方式。一般这种常量需要全文大写字母。表示只占有一段不能改变的存储空间
2 对可变类的对象运用final时表示该引用恒定不变,就是一旦该引用初始化指向一个对象时就无法再指向另一个对象。如下列代码:
package BasicTest;
class Value{
int i;
public Value( int i){
this.i = i;
}
public setValue(int i){
this.i = i;
}
}
public class FinalTest {
private final Value value = new Value(10);
public static void main(String[] args){
FinalTest ft = new FinalTest();
Value v1 = new Value(2);
ft.value = v1; //error
}
}
此时编译器就会报错The final field FinalTest.value cannot be assigned
但是不可变的只是这个引用所指的对象,不代表对象本身不可变的,通过这个引用是可以改变对象的状态的。我们看一个完整的列子:
class Value{
int i;
public Value( int i){
this.i = i;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
class Test{
public static final Value v1= new Value(10);
private final Value v2 = new Value(10);
public static Value v3 = new Value(10);
public Value getV1() {
return v1;
}
public Value getV2() {
return v2;
}
public Value getV3() {
return v3;
}
public void setV3(Value v3) {
Test.v3 = v3;
}
}
public class FinalTest {
public static void main(String[] args){
Test t1 = new Test();
Test.v3 = new Value(3);
System.out.println("v1:"+Test.v1.i);
System.out.println("v2:"+t1.getV2().i);
System.out.println("v3:"+t1.getV3().i);
t1.getV1().setI(2);
t1.getV2().setI(2);
t1.getV3().setI(2);
System.out.println("v1:"+Test.v1.i);
System.out.println("v2:"+t1.getV2().i);
System.out.println("v3:"+t1.getV3().i);
}
}
输出结果为:
从结果上来看,不论对象被定义为static final 还是final被固定的只是引用而不是对象的值,同时被final定义的都是先要赋值的。
补充一点,java可以在参数中生平参数final,表示你可以读这个参数但是无法修改这个参数,这一特性主要用在匿名内部类中传递参数。
二 final 方法
使用final方法表示该方法锁定,以防子类继承该类后覆盖该方法。 类中的所有private 方法都隐式的指定为final,所以给private添加final没有任何意义。值得注意的是private修饰的final方法编译器允许子类“覆盖”,如下列代码:
class Value{
int i;
public Value( int i){
this.i = i;
}
private final void f(){
System.out.println("this is father");
}
}
class ValueC extends Value {
public ValueC(int i) {
super(i);
}
private final void f(){
System.out.println("this is Children ");
}
}
其实此时并没有覆盖父类的方法,仅是生成了一个同名的新的方法,也不是重载,他们分属各自的类而已。
三 final 类
给整了类声明final表示你不允许该类被继承,对该类不允许有改动。一般定义基本类型的的类都是用final定义,为不可变类,如String类的源码:
final类是禁止继承的,所以所有的方法都隐式为final,给不给方法添加final都不会添任何意义。