一 final含义
final在Java中是一个保留的关键字,可以声明成员变量、方法、类以及本地变量。一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译错误。
你可能出于两种理解而需要阻止改变:设计或效率。
final类不能被继承,没有子类,final类中的方法默认是final的。
final方法不能被子类的方法覆盖,但可以被继承。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final不能用于修饰构造方法。
final方法不能被子类的方法覆盖,但可以被继承。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final不能用于修饰构造方法。
二 final类
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。Java中有许多类是final的,譬如String, Interger以及其他包装类。
三final 方法
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效:一个final方法被调用时会转为内嵌(inline)调用,不会使用常规的压栈方式(将参数压入栈,
跳至方法代码处并执行,然后跳回并清除栈中的参数,处理返回值。),使得运行效率较高,尤其是在方法体较简单的情况下。父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效:一个final方法被调用时会转为内嵌(inline)调用,不会使用常规的压栈方式(将参数压入栈,
跳至方法代码处并执行,然后跳回并清除栈中的参数,处理返回值。),使得运行效率较高,尤其是在方法体较简单的情况下。父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
四final变量
用final修饰的成员变量表示常量,值一旦给定就无法改变!
final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。
final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。
总结:对于final类型的变量,对于不加static我们可以有两种方式给它赋值:声明变量时直接赋值;在构造方法中完成赋值,如果一个类有多 个构造方法,就要保证在每个构造方法中都要完成对该final类型变量的初始化工作。对于一个变量既是final又是static的,我们可以在声明变量 时直接赋值 或者静态代码块初始化。
关于final与JVM关系:
- class FinalTest{
- public static final int a = 6/3;
- static{
- System.out.println("FinalTest static block");
- }
- }
- public class Test3 {
- public static void main(String[] args) {
- System.out.println(FinalTest.a);
- }
- }
因为a是static final变量,且它等于6/3,在编译的时候就可以知道它的值,所以直接访问a的值不会引起FinalTest类的初
始化。作为表现,也就是static静态代码快不会被加载。
运行结果为:
2
下面的例子是讲,当子类被主动访问的时候,会引起其直接父类的初始化,也就是static静态代码块的加载
- class Parent{
- static int a = 3;
- static{
- System.out.println("Parent static block");
- }
- }
- class Child extends Parent{
- static int b = 4;
- static{
- System.out.println("Chind static block");
- }
- }
- public class Test5 {
- public static void main(String[] args) {
- System.out.println(Child.b);
- }
- }
因为直接访问Child,b,会先初始化Parent类,然后初始化Child类。
运行结果为
- Parent static block
- Chind static block
- 4
五 final参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
public
class Test4 {
public static void main(String[] args) {
new Test4().f1(2);
}
public void f1( final int i) {
//i++; //i是final类型的,值不允许改变的.
System.out.print(i);
}
}
public static void main(String[] args) {
new Test4().f1(2);
}
public void f1( final int i) {
//i++; //i是final类型的,值不允许改变的.
System.out.print(i);
}
}
********************************************************
问题:static
final
和static初始化都是什么时候初始化的?
回答:static final 见上面。static就是
JAVA类首次装入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的。可以参照上篇的static。
参考:
http://lavasoft.blog.51cto.com/62575/18771/
http://www.importnew.com/7553.html
http://blog.csdn.net/a352193394/article/details/7342583