今天有人问我,Java的对象或者类型修改用Final.
Java中的final关键字通常的指的是“这是无法改变的”。它可能被做为三种的修饰词.------数据,方法,类。
一 final数据
1.在修饰基本类型时,表示它是一个常量,在定义时必须给予赋值.
特别的一个既是static又是final 的字段只占据一段不能改变的存储空间。
2.在修饰对象或者数组时,它表示对对象或数组的引用恒定不变,然而对象本身却是可以修改的.
空白final:声明为final但末给定初值的字段,但必须确保空白final在使用前被初始化,一般在构造方法完成。
final参数:在方法的参数列表以声明的方式将参数指明为final,这意味着在方法里无法修改参数的引用所指向的对象。
二 final方法
1. 把方法锁定,使得在子类(导出类)中不能修改它的含义。
2.效率,一个final方法被调用时会转为内嵌调用,不会使用常规的压栈方式,使得运行效率较高,尤其是在方法体较简单的情况下,
但也并不绝对。(与C++中的inline关键字类似)
特别的:类中的所有private方法都隐式地指定为是final,所以在继承关系中不存在覆盖问题。
三 final类
声明为final的类不能派生出了子类,也就是不能被继承,一个final类中的所有方法都隐式地指定为final.
可能有人会问了,你说不能改变,你说只占据一段存储空间,你懂JVM的编译规则吗?
首先举下Final数据的例子.
public class MyClass {
private static final int aa=1;
int b=3;
public int add(int a,int b){
return a+b;
}
}
Javac MyClass
public class com.tag2.jvm.MyClass {
// Field descriptor #6 I
private static final int aa = 1;
// Field descriptor #6 I
int b;
// Method descriptor #11 ()V
// Stack: 2, Locals: 1
public MyClass();
0 aload_0 [this] //0:变量到操作数栈
1 invokespecial java.lang.Object() [13] //1:调用需要特殊处理的实例方法:invokespecial
4 aload_0 [this] //4:变量到操作数栈
5 iconst_3 //5:常数到操作数栈
6 putfield com.tag2.jvm.MyClass.b : int [15] //6:访问类的域和类实例域,com.tag2.jvm.MyClass.a : int [15]
9 return
Line numbers:
[pc: 0, line: 3]
[pc: 4, line: 5]
[pc: 9, line: 3]
Local variable table:
[pc: 0, pc: 10] local: this index: 0 type: com.tag2.jvm.MyClass
...
}
大家看以上的编程Class文件,通过JVM指令解析,一般操作步骤是,先声名变量 int aa,int b.然后再把常数也压到栈中,最后赋值的过程。
大家看到final修改的变量不需要赋值[一个既是static又是final 的字段只占据一段不能改变的存储空间]
(声名为静态的是类变量,其访问速度会快(少了一个赋值过程),也就是固定的内存地址,用final修改就是不可改变的存储空间)
用final修改意为不可改为,这意味着在方法里无法修改参数的引用所指向的对象。[引用恒定不变 ,对象本身可以修改]
我上节介绍了设计模式之单例模式,其中Spring用到了两个synchronized (this.startupShutdownMonitor) synchronized (this.singletonObjects)
其中两个对象都是final类型的[Spring的锁对象一般都是Final的,不可改变的,也就保证了其原子性]。