java的关键字final的含义通常指“这是无法改变的”,不想改变出于两种理由。
1、设计。
2、效率
谈论一些用到final的三种情况。数据、方法和类
1、数据
有时候数据恒定不变是由意义的,
例如1 一个永不改变编译时的常量。
例如2:一个在运行时被初始化的值,而你不希望它被改变。
在java中这些常量必须是基本类型,以关键字final表示。在编译时执行计算,减轻运行时负担。对基本类型final使数值恒定不变。而对于对象引用,final使引用恒定不变,但是对象自身是可以修改的,java并没有提供对象恒定不变的途径。
即是static又是final的域,将用大小表示,并使用下划线分割单词。
package pdmtest.cl;
public class FinalData {
// Can be compile-time constants
final int i1 = 9;
static final int I2 = 99;
// Typical public constant:
public static final int I3 = 39;
// Cannot be compile-time constants:
final int i4 = (int) (Math.random() * 20);
static final int i5 = (int) (Math.random() * 20);
Value v1 = new Value();
final Value v2 = new Value();
static final Value v3 = new Value();
// ! final Value v4; // Pre-Java 1.1 Error:
// no initializer
// Arrays:
final int[] a = { 1, 2, 3, 4, 5, 6 };
public void print(String id) {
v3.i = (int) (Math.random() * 20);
v2.i = (int) (Math.random() * 20);
System.out.println(id + ": " + "i4 = " + i4 + ", i5 = " + i5+ ", v3 = "+v3.i+ ", v2 = "+v2.i);
}
public static void main(String[] args) {
FinalData fd1 = new FinalData();
// ! fd1.i1++; // Error: can't change value
fd1.v2.i++; // Object isn't constant!
fd1.v1 = new Value(); // OK -- not final
for (int i = 0; i < fd1.a.length; i++)
fd1.a[i]++; // Object isn't constant!
// ! fd1.v2 = new Value(); // Error: Can't
// ! fd1.v3 = new Value(); // change handle
// ! fd1.a = new int[3];
fd1.print("fd1");
FinalData fd2 = new FinalData();
fd1.print("fd1");
fd2.print("fd2");
}
}
output
fd1: i4 = 18, i5 = 9, v3 = 2, v2 = 18
fd1: i4 = 18, i5 = 9, v3 = 17, v2 = 5
fd2: i4 = 2, i5 = 9, v3 = 3, v2 = 6
空白final
Java 1.1 允许我们创建“空白final”,它们属于一些特殊的字段。尽管被声明成final,但却未得到一个
初始值。无论在哪种情况下,空白final 都必须在实际使用前得到正确的初始化。
class Poppet { }
class BlankFinal {
final int i = 0; // Initialized final
final int j; // Blank final
final Poppet p; // Blank final handle
// Blank finals MUST be initialized
// in the constructor:
BlankFinal() {
j = 1; // Initialize blank final
p = new Poppet();
}
BlankFinal(int x) {
j = x; // Initialize blank final
p = new Poppet();
}
public static void main(String[] args) {
BlankFinal bf = new BlankFinal();
}
} ///:~
现在强行要求我们对final 进行赋值处理——要么在定义字段时使用一个表达 式,要么在每个构建器中
final参数
java允许在参数列表中以声明的方式将参数指明为final,意味着你无法改变参数引用所指向的对象。
package pdmtest.cl;
public class FinalArguments {
void with(final Gizmo g){
//g = new Gizmo();//final object 不可以赋值
}
void f(final int i){
//i=2;不可以赋值
}
int g(final int x){
return x+1;
}
public static void main(String[] args) {
FinalArguments f = new FinalArguments();
System.out.println(f.g(1));
Gizmo g = new Gizmo();
f.with(g);
}
}
这一特性主要是向匿名内部类传递数据。
final方法
使用final方法有两个原因。
第一个原因把方法锁定,防止任何类修改它的含义。出于设计考虑。
第二个原因是效率。将方法指明给final就是同意编译器针对该方法的所有调用都转为内嵌调用。
final类
当将某个类设计为final时,表明你不打算集成该类,而且也不允许别人这么做。
将类定义成final 后,结果只是禁止进行继承——没有更多的限制。然
而,由于它禁止了继承,所以一个final 类中的所有方法都默认为final
package pdmtest.cl;
class SmallBrain {
}
final class Dinosaur {
int i = 7;
int j = 1;
SmallBrain x = new SmallBrain();
void f() {
}
}
// ! class Further extends Dinosaur {}
// error: Cannot extend final class 'Dinosaur'
public class Jurassic {
public static void main(String[] args) {
Dinosaur n = new Dinosaur();
n.f();
n.i = 40;
n.j++;
}
}