Java中的final关键字意思是“最终的”,“无法改变的”。
值得提的是:final类不能被继承,它没有子类
final类中的方法默认是final的
final方法不能被子类重定义,但是可以被继承
final变量只能一次赋值,往后不可更改
final不能用来修饰构造方法
主要有5种:①final修饰普通变量 ②空白final数据成员 ③final修饰方法参数 ④final修饰方法 ⑤final修饰类
对于①:
对于基本的数据成员,final会将值变成一个常量。但是对于对象句柄(对象句柄,就是一个对象变量),final会将句柄变成一个常量,而且声明时的同时必须初始化。虽然对象句柄是常量,但是对象本身是可以修改的,且对象里的成员若没有final修饰,就不是常量,是可以改变的。
例如以下:
class Value{
int i=1;
}
public class FinalData {
final int i1=9;
static final int i2=99;
public static final int i3=39;
final int i4=(int)(Math.random()*20);
static final int i5=(int)(Math.random()*20);
Value v1=new Value();
final Value v2=new Value();
// final Value v4; 此处错误!必须在类的初始化中完成对v4的初始化
final int[]a={1,2,3,4,5,6};
public void print(String id){
System.out.println(id+":"+"i4="+i4+",i5="+i5);
}
public static void main(String[] args){
FinalData fd1=new FinalData();
// fd1.i1++; 此处错误!不能对常量进行加一
fd1.v2.i++; //这里是正确的,尽管v2是常量,但是v2里面的i不是常量,是可以进行改变的
fd1.v1=new Value(); //这里是正确的,v1没有声明为final,可以改变
for(int i=0;i<fd1.a.length;i++)
fd1.a[i]++; //这里是正确的,因为final int[]={1,2,3,4,5,6}表示的是常量数组,而数组里值不是常量
//fd1.a=new int[3]; 此处错误,常量数组不可改变
//fd1.v2=nwe Value(); 此处错误,v3是常量
//fd1.v3=new Value(); 此处错误,v2是常量
fd1.print("fd1");
System.out.println("Creating new FinalData");
FinalData fd2=new FinalData();
fd1.print("fd1");
fd2.print("fd2");
}
}
值得注意的是这里的final int i4=(int)(Math.random()*20);static final int i5=(int)(Math.random()*20);中,i4和i5是随机生成的数,不能由于某个数据的属性是final,就认定它的值一定能在编译时期就是确定的,因为你再运行一次,它们的值就会可能不同。其他要说的就是:public表示可以在包外使用,static表示它们只有“一个”,final不用说了,表示常量。
对于②:
空白final数据成员这个没什么好说的,就是Java允许创建一种特殊的数据成员,虽然声明为final变量,但却没有赋一个初始值。但是!你用空白final数据成员前,必须对它进行正确的初始化。
例如先前定义的final int i;
为了确保final数据使用前得到正确的初始化,那么你就要在构造方法中对空白final数据成员进行初始化。
#构造方法#(){
i=1;
}
对于③:
final修饰方法参数,意味着方法的内部,不能改变final修饰的参数。是否想到了c++的const关键字
class TestFinal{
public void spin(){
}
}
public class FinalArgument {
void with(final TestFinal g){
//g=new Gizmo(); 次数错误,g是final的,不可改变
g.spin();
}
void without(TestFinal g){
g=new TestFinal();
g.spin();
}
//void f(final int i){ 此处错误,不能改变参数final常量i
// i++;
// }
int g(final int i){
return i+1; //只能对final参数做简单的引用
}
public static void main(String[] args){
FinalArgument bf=new FinalArgument();
bf.without(new TestFinal()); //这里可以传递一个NULL指针,不会有编译错误,即bf.without(NULL);
bf.with(new TestFinal());
}
}
在f()中,只能读取参数,不能改变它。在g()中,返回值的改变没有发生在变量本身,只是将final的参数i加了1后直接进行返回。
对于④:
也就是说final修饰的方法不能被重定义。一是为了加锁,二是为了效率,具体的这里不说,因为我也不清楚。
对于⑤:
如果整个类是用final修饰的,出于安全考虑,就是不允许从这个类继承任何内容。有一点要说的是,final类中的成员可以是final的,也可以不是。结果只是禁止继承,没有对其中的成员限制。
例如说:
class Aaa{
....
}
final class Bbb{
....
Aaa a=new Aaa();
}
若class Ccc extends Bbb{则是错误的!
....
}