您的位置:首页 > 编程语言 > Java开发

Java关键字之final详解

2016-01-29 10:18 295 查看
在我们编写Java程序时总会根据需求将变量、方法、类设置成static(静态)或final(最终),熟练掌握final用法是必须的,现在我们就来详细了解final关键字!

一、final概述

概念:由字面可以了解,final有最终态,无法改变的意思。

使用目的:为了阻止改变与提高效率。

高效原因:Java内嵌机制,final方法会在编译的过程中利用内嵌机制进行inline优化。

inline优化是指:在编译的时候直接调用方法代码替换,也就是内嵌,而不是在运行时调用方法。

inline需要在编译的时候就知道最后要用哪个方法。

显然,非final是不行的。

非final方法可能在子类中被重写,由于可能出现多态的情况,编译器在编译阶段

并不能确定将来调用方法的对象的真正类型,也就无法确定到底调用哪个方法。)

修饰对象:

1、非抽象类,由于被final修饰的类是不能被继承的,而抽象类必须被继承才有意义。

2、非抽象方法,由于被final修饰的方法是不能被重写的,而抽象方法必须被重写才有意义。

3、变量或常量。

注意:

1、final不能修饰构造方法。

2、父类的private方法是不能被子类重写的,因为private方法默认是final的。

二、具体用法

1、修饰类

final类不能被继承,所有其成员与方法自然没有机会被覆盖,默认是final的。所以在将类设计成final类的时候,一定要特别慎重考虑,确定这个类不需要有子类,类实现不能被改变,类不能被扩展的时候才能用final修饰。

注:Java中String类就是一个final类。

2、修饰方法

如果一个类不允许其子类覆盖某个方法,则可以把这个方法用final修饰。

这样做的目的可在《Java编程思想》中查到:

“使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。”

public class Test1 {
public static void main(String[] args) {
// TODO 自动生成方法存根
}
public void f1() {
System.out.println("f1");
}
//无法被子类覆盖的方法
public final void f2() {
System.out.println("f2");
}
public void f3() {
System.out.println("f3");
}
private void f4() {
System.out.println("f4");
}
}
public class Test2 extends Test1 {

public void f1(){
System.out.println("Test1父类方法f1被覆盖!");
}
public static void main(String[] args) {
Test2 t=new Test2();
t.f1();
t.f2(); //调用从父类继承过来的final方法
t.f3(); //调用从父类继承过来的方法
//t.f4(); //调用失败,无法从父类继承获得
}
}

3、修饰变量(重点)

1、final修饰基本数据类型变量,则其数值一旦被初始化就不能被更改。

2、final修饰引用变量(如ObjectName obj = new ObjectName();中obj就是一个引用变量,指向堆内存中对象空间的首地址),则其初始化后就不能修改引用指向另一个对象。

public class Test2 {
private final String S = "final实例变量S";
private final int A = 100;
public final int B = 90;

public static final int C = 80;
private static final int D = 70;

public final int E; //final空白,必须在初始化对象的时候赋初值

public Test3(int x) {
E = x;
}

/**
* @param args
*/
public static void main(String[] args) {
Test3 t = new Test3(2);
//t.A=101;    //出错,final变量的值一旦给定就无法改变
//t.B=91; //出错,final变量的值一旦给定就无法改变
//t.C=81; //出错,final变量的值一旦给定就无法改变
//t.D=71; //出错,final变量的值一旦给定就无法改变

System.out.println(t.A);
System.out.println(t.B);
System.out.println(t.C); //不推荐用对象方式访问静态字段
System.out.println(t.D); //不推荐用对象方式访问静态字段
System.out.println(Test3.C);
System.out.println(Test3.D);
//System.out.println(Test3.E); //出错,因为E为final空白,依据不同对象值有所不同.
System.out.println(t.E);

Test3 t1 = new Test3(3);
System.out.println(t1.E); //final空白变量E依据对象的不同而不同
}

private void test() {
System.out.println(new Test3(1).A);
System.out.println(Test3.C);
System.out.println(Test3.D);
}

public void test2() {
final int a;     //final空白,在需要的时候才赋值
final int b = 4;    //局部常量--final用于局部变量的情形
final int c;    //final空白,一直没有给赋值.
a = 3;
//a=4;    出错,已经给赋过值了.
//b=2; 出错,已经给赋过值了.
}
}
四、修饰参数

当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。

public class Test3 {
public static void main(String[] args) {
new Test4().f1(2);
}

public void f1(final int i) {
//i++;    //i是final类型的,值不允许改变的.
System.out.print(i);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java