Java关键字fianl会使用到的三个地方:数据、方法和类。
1.final用于数据。
final用于数据时,可以根据数据的类型分为两种情况,一种是基本数据类型,一类是对象。当用于基本数据类型时,表示final修饰的值是不变的,用于对象时,表示的是final修饰的变量其引用时不变的(但是该对象的数值是可以改变的,c语言中意思就是地址不能变,此地址指向的值可以改变)。
看下例子:
class Value{
private int i ;
public Value(int i){this.i = i;}
public void change(int i){this.i = i;}
public int getValue(){return i;}
}
第二个类中定义了如下变量
private Value v1 =new Value(11);
private final Value v2 =new Value(22);
private static final Value V3 = new Value(33);
private int value =0;
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
public static final int VALUE_THREE = 999;
首先看对基本数据类型的分析:
value是没有加final修饰的,因此它的数据可以在函数运行产生诸如:value++,value=10等修改它数据的函数。
valueOne加了final,在函数运行时候,如果出现valueOne++或者valueOne=1等则会报错。
VALUE_TWO加上了static final的修饰,表示一段不能改变的存储空间。大致作用同valueOne。
VALUE_THREE与VALUE_TWO的差别在于VAlue_THREE可以在包外被其他类所引用。
再看对对象的引用。
v1是一个正常的对象,他可以出现v1 = new Value(22);这样的语句,意思就是v1引用的对象发生了改变。
v2加了final的修饰,表示他的引用不可以改变,即出现了v2 = new Value(22)这样的语句是错误的。但是他可以出改变i的数据,比如调用v2.chane(1),就是改变了i的数值大小。
v3的效果同v2。
额外补充:
a>.空白final:所谓空白final意思是申明但又没给初值的域。 比如定义一个private final int a;定义了,但没给初值。但是它如果没给初值,则必须在构造器中用表达式对其进行赋值。
b>.final参数:当基本类型的参数被指明为final,表示只可以读,不可以修改。
2.final用于方法:
原因:《Thing in Java》里面阐述原因有两点:①方法锁定,让其在继承中方法的行为保持不变并且不会被覆盖。换句话说就是final方法无法被重写,②:效率,在Java的早期实现中,当一个方法申明了final,编译器针对此方法的所有调用都改为内嵌调用。在《深入理解计算机系统》中有提到,对于普通的方法,在编译连接期间,在调用方法的地方,将方法的代码插入(c语言),而内嵌调用则直接访问方法的地址(这个地方是我个人看Thinking in Java自己想的,如果有不对,还望提出)。
补充说明:private和final:类中所有private的方法隐式的被定义为final的,由于无法取到private方法,因此就无法有覆盖它一说,新的方法就被看做以前没有这个方法,新增了一个一样。因此,可以覆盖一个private方法是奏效的。看例子:
class withfinal{
private final void p(){
System.out.println("withfinal.p");
}
public final void pp(){
System.out.println("withfianl.pp");
}
}
class overriding extends withfinal{
private final void p(){
System.out.println("overriding.p");
}
/*
public final void pp(){
这句话会报错,会提示你无法覆盖pp函数
}
<pre name="code" class="java">*/
}class withfinal1 extends withfinal{
public final void p(){
System.out.println("withfinal1.p");
}
}
public class method {
public static void main(String[] args) {
// TODO Auto-generated method stub
overriding1 a = new overriding1();
a.p();
withfinal w = a ;
// w.p() ; 这句话报错,因为w.p()调用的事withfinal的p(),她是private的,不可见,所以报错。
}
}
3.final用于类
当类前面被final申明时,就意味着该类不能被继承。