java编程思想--final关键字

来源:互联网 发布:程序员培训班多少钱 编辑:程序博客网 时间:2024/04/28 08:10

讨论final使用的三种情况:数据,方法和类

final数据

1,一个永不改变的编译时常量

2,一个在运行时被初始化的值,而你不希望它被改变

import java.util.*;class Value{int i;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;}private final int valueOne=9;private static final int VALUE_TWO=99;public static final int VALUE_THREE=39;private final int i4=rand.nextInt(20);static final int INT_5=rand.nextInt(20);private Value v1=new Value(1);private final Value v2=new Value(22);private static final Value VAL_3=new Value(33);private final int[] a={1,2,3,4,5,6};public String toString(){return id+": "+"i4="+i4+",INT_5:"+INT_5;}/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubFinalData fd1=new FinalData("fd1");fd1.v2.i++;fd1.v1=new Value(9);for(int i=0;i<fd1.a.length;i++)fd1.a[i]++;System.out.println(fd1);System.out.println("Create new FinalData");FinalData fd2=new FinalData("fd2");System.out.println(fd1);System.out.println(fd2);}}

结果

fd1: i4=15,INT_518
Create new FinalData
fd1: i4=15,INT_518
fd2: i4=13,INT_518

解析:


i4仅仅是final类型,分别在两个对象中各开辟一块空间

static final 仅使用一段不能改变的空间,所以INT_5值不变


空白final

指被声明为final但又未给定初始值的域,编译器保证空白final使用前必须被初始化

final类型参数

无法在方法中更改参数引用所指向的对象


final方法

类中所有private方法都隐式地制定为是final的,一个类继承基类的private方法(final),可以覆盖private final方法。但如果在导出类中以相同的名称生成一个public,protected或包访问权限方法的话,此时并没有覆盖该方法,仅是生成了一个新的方法。

将方法声明为final那有两个原因,第一就是说明你已经知道这个方法提供的功能已经满足你要求,不需要进行扩展,并且也不允许任何从此类继承的类来覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。第二就是允许编译器将所有对此方法的调用转化为inline调用的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用final进行方法定义。

import javax.swing.text.GapContent;import org.omg.CORBA.PRIVATE_MEMBER;class WithFinals{private final void f(){System.out.println("WithFinals.f()");}private void g(){System.out.println("WithFinals.g()");}}class OverridingPrivate extends WithFinals{private final void f(){System.out.println("OverridingPrivate.f()");}private void g(){System.out.println("OverridingPrivate.g()");}}class OverridingPrivate2 extends OverridingPrivate{public final void f(){System.out.println("OverridingPrivate2.f()");}public void g(){System.out.println("OverridingPrivate2.g()");}}public class FinalOverridingIilusion {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubOverridingPrivate2 op2=new OverridingPrivate2();op2.f();op2.g();}}

结果

OverridingPrivate2.f()
OverridingPrivate2.g()
如果将 WithFinals的g()方法前private改为final,则后面的覆盖就会报错,因为单单的final方法不允许覆盖,可以直接调用

final类

当某个类整体定义为final,表明了不能继承该类。该类的设计永不需要做任何改动 ,或出于安全考虑,不希望它有子类

final类的域可以选择是什么类型,是或不是fianl,默认指定final,无法覆盖它们