final关键字

来源:互联网 发布:p2p网络电视 编辑:程序博客网 时间:2024/05/22 06:21

final关键字的用法

概念

java的关键字final指的是“这是无法被改变的”。(不想做改变可能出于两种理由:设计和效率,在下面会详细讨论)


final可能用到的地方

1. 数据


例如:

1. 一个永不改变的编译时常量。(注意:必须是基本类型,使用时必须赋初值)
2. 一个在初始化时被初始化的值,而你不希望它被改变。

注意:

1.对于基本类型 ,final使其值不变;对于对象引用,final使其引用恒定不变。一旦将其初始化指向一个对象,就无法再把它改为指向另一个对象 。(然而对象本身是可以被修改的)
2.根据惯例,既是static又是final的域(即编译期常数)将用大写表示,并用下划线分隔各个单词。
3.必须在域的定义处或者每个构造器中用表达式对final进行赋值,这正是final域在使用前总是被初始化的原因所在。

值得一提的是:我们不能因为某数据被final修饰就认为在编译期间就可以知道它的值,若用随机数赋值就说明了这点。(见下列代码)

import java.util.*;class Value {  int i; // Package access  public Value(int i) { this.i = i; }}public class FinalData {  private static Random rand = new Random(47);  private String id;  public FinalData(String id) { this.id = id; }  // Can be compile-time constants:  private final int valueOne = 9;  private static final int VALUE_TWO = 99;  // Typical public constant:  public static final int VALUE_THREE = 39;  // Cannot be compile-time constants:  private final int i4 = rand.nextInt(20);  static final int INT_5 = rand.nextInt(20);  private Value v1 = new Value(11);  private final Value v2 = new Value(22);  private static final Value VAL_3 = new Value(33);  // Arrays:  private final int[] a = { 1, 2, 3, 4, 5, 6 };  public String toString() {    return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;  }  public static void main(String[] args) {    FinalData fd1 = new FinalData("fd1");    //! fd1.valueOne++; // Error: can't change value    fd1.v2.i++; // Object isn't constant!    fd1.v1 = new Value(9); // OK -- not final    for(int i = 0; i < fd1.a.length; i++)      fd1.a[i]++; // Object isn't constant!    //! fd1.v2 = new Value(0); // Error: Can't    //! fd1.VAL_3 = new Value(1); // change reference    //! fd1.a = new int[3];    System.out.println(fd1);    System.out.println("Creating new FinalData");    FinalData fd2 = new FinalData("fd2");    System.out.println(fd1);    System.out.println(fd2);  }} /* Output:fd1: i4 = 15, INT_5 = 18Creating new FinalDatafd1: i4 = 15, INT_5 = 18fd2: i4 = 13, INT_5 = 18*///:~

final参数

Java允许在参数列表中以声明的形式将参数指明为final。这意味着你无法在方法中改变参数引用所指向的对象。


2. 方法

使用final方法的原因有两个:

  1. 将方法锁定,以防任何基层类修改它的含义。这是出于设计的考虑;想要确保在继承中使方法行为保持不变,并且不会被覆盖。
  2. 过去建议使用final方法是因为效率。在Java早期实现中,如果将一个方法指明为final,就是同意编译器将针对该方法的所有调用转为内嵌调用。当编译器发现一个final方法调用命令时,会根据自己的谨慎判断,跳过插入程序代码这种正常方式而执行方法调用机制(将参数压入栈,跳至方法代码处并执行,然后跳回并清理栈中的参数,处理返回值),并且以方法体中的实际代码的副本来代替方法使用。

注意:在最近的Java版本中,虚拟机可以探测到这些情况,并优化去掉这些效率反而降低的额外的内嵌调用,因此不再需要使用final方法来进行优化了。应当让虚拟机和JVM去处理效率问题,只有在想要明确禁止覆盖时,才将方法设置为final。

final 和 private

类中的所有private方法都隐式地指定为final的。由于无法取用private方法所以也就无法覆盖它。可以对private方法添加final修饰词,但这没有意义。


3. 类


当将某个类用final修饰时,就表明你不打算继承它,而且也不允许别人这么做。换句话说,出于某种考虑,你对该类的设计永不需要做任何变动,或者是出于安全的考虑,你不希望它有子类。

然而,由于final类禁止继承,所以final类中所有方法都隐式指定为final的,因为无法覆盖他们。在final类中可以给方法添加final修饰词,但这不会增添任何意义。

忠告:

在设计类的时候最好不要用final修饰方法,这会妨碍其他程序员在项目中通过继承来复用你的类,而这只是因为你没有想到它会以那种方式被运用。


总结

  1. 对于基本类型,final使其值不变;对于对象引用,final使其应用恒定不变。一旦将其初始化指向一个对象,就无法再把它改为指向另一个对象 。
  2. 根据惯例,既是static又是final的域(即编译期常数)将用大写表示,并用下划线分隔各个单词。
  3. 必须在域的定义处或者每个构造器中用表达式对final进行赋值,这正是final域在使用前总是被初始化的原因所在。
  4. 我们不能因为某数据被final修饰就认为在编译期间就可以知道它的值。
  5. Java允许在参数列表中以声明的形式将参数指明为final。这意味着你无法在方法中改变参数引用所指向的对象。
  6. Java允许在参数列表中以声明的形式将参数指明为final。这意味着你无法在方法中改变参数引用所指向的对象。
  7. 类中的所有private方法都隐式地指定为final的。由于无法取用private方法所以也就无法覆盖它。可以对private方法添加final修饰词,但这没有意义。
  8. 当将某个类用final修饰时,就表明你不打算继承它,而且也不允许别人这么做。
  9. 在设计类的时候最好不要用final修饰方法,这会妨碍其他程序员在项目中通过继承来复用你的类,而这只是因为你没有想到它会以那种方式被运用。
原创粉丝点击