在Java中,声明类、变量和方法时,可使用关键字final来修饰。final所修饰的数据具有“终态”的特征,表示“最终的”意思。具体规定如下:

  final修饰的类不能被继承。

  final修饰的方法不能被子类重写。

  final修饰的变量(成员变量或局部变量)即成为常量,只能赋值一次。

  final修饰的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有一次赋值的机会,而且只能在构造方法中显式赋值,然后才能使用。

  final修饰的局部变量可以只声明不赋值,然后再进行一次性的赋值。

  final一般用于修饰那些通用性的功能、实现方式或取值不能随意被改变的数据,以避免被误用,例如实现数学三角方法、幂运算等功能的方法,以及数学常量π=3.141593、e=2.71828等。

  事实上,为确保终态性,提供了上述方法和常量的java.lang.Math类也已被定义为final的。

  需要注意的是,如果将引用类型(任何类的类型)的变量标记为final,那么该变量不能指向任何其它对象。但可以改变对象的内容,因为只有引用本身是final的。

  如果变量被标记为final,其结果是使它成为常数。想改变final变量的值会导致一个编译错误。下面是一个正确定义final变量的例子:

  public final int MAX_ARRAY_SIZE=25;//常量名一般大写

  常量因为有final修饰,所以不能被继承。

  请看下面的代码:

  public final class Demo{

  public static final int TOTAL_NUMBER=5;

  public int id;

  public Demo(){

  //非法,对final变量TOTAL_NUMBER进行二次赋值了

  //因为++TOTAL_NUMBER相当于TOTAL_NUMBER=TOTAL_NUMBER+1

  id=++TOTAL_NUMBER;

  }

  public static void main(String[]args){

  final Demo t=new Demo();

  final int i=10;

  final int j;

  j=20;

  j=30;//非法,对final变量进行二次赋值

  }

  }

  final也可以用来修饰类(放在class关键字前面),阻止该类再派生出子类,例如Java.lang.String就是一个final类。这样做是出于安全原因,因为要保证一旦有字符串的引用,就必须是类String的字符串,而不是某个其它类的字符串(String类可能被恶意继承并篡改)。

  方法也可以被final修饰,被final修饰的方法不能被覆盖;变量也可以被final修饰,被final修饰的变量在创建对象以后就不允许改变它们的值了。一旦将一个类声明为final,那么该类包含的方法也将被隐式地声明为final,但是变量不是。

  被final修饰的方法为静态绑定,不会产生多态(动态绑定),程序在运行时不需要再检索方法表,能够提高代码的执行效率。在Java中,被static或private修饰的方法会被隐式的声明为final,因为动态绑定没有意义。

  由于动态绑定会消耗资源并且很多时候没有必要,所以有一些程序员认为:除非有足够的理由使用多态性,否则应该将所有的方法都用final修饰。

  这样的认识未免有些偏激,因为JVM中的即时编译器能够实时监控程序的运行信息,可以准确的知道类之间的继承关系。如果一个方法没有被覆盖并且很短,编译器就能够对它进行优化处理,这个过程为称为内联(inlining)。例如,内联调用e.getName()将被替换为访问e.name变量。这是一项很有意义的改进,这是由于CPU在处理调用方法的指令时,使用的分支转移会扰乱预取指令的策略,所以,这被视为不受欢迎的。然而,如果getName()在另外一个类中被覆盖,那么编译器就无法知道覆盖的代码将会做什么操作,因此也就不能对它进行内联处理了。

  更多技术教程,请关注技术教程网www.jishujc.com