Java中的final修饰符

一、Java中final修饰符可以修饰类、方法、变量,基本规则如下:

1)用final修饰的类无法被继承,没有子类

2)用final修饰的 方法不能被重写或隐藏
  ①使用final修饰的实例方法在其所属类的子类中不能被重写(override);

  ②使用final修饰的静态方法在其所属类的子类中不能被隐藏(hide);

3)用final修饰的变量 “最多只能赋值一次”,在赋值方式上不同类型的变量稍有不同:
  ①静态变量必须 “明确赋值”一次(不能使用类型缺省值);
           作为类成员的静态变量,赋值可以在其 声明中通过初始化表达式完成,也可以在 静态初始化块中进行;(2处)

           作为接口成员的静态变量,赋值只能在其声明中通过初始化表达式完成;(1处)

  ②实例变量必须 “明确赋值”一次(不能使用类型缺省值);

            赋值可以在其声明中通过初始化表达式完成,也可以在实例初始化块构造器中进行;(3处)

  ③ 方法参数变量  methodName(final Type ParamName)

            在方法被调用时创建,同时被初始化为对应实参值。终止于方法体(body)结束,在此期间其值不能改变;

  ④ 构造器参数变量  constructor(final Type ParamName)

            在构造器被调用(通过实例创建表达式new ClassName(ParamList)或显示的构造器调用super(ParamList))时创建,同时被初始化为对应实参值,终止于构造器方法体结束,在此期间其值不能改变;

  ⑤ 异常处理器参数变量 catch(final ExceptionType ParamName)

            在有异常被try语句的catch子句捕捉到时创建,同时被初始化为实际的异常对象,终止于catch语句块结束,在此期间其值不能改变;

  ⑥局部变量在其值被访问之前必须被明确赋值; {final Type VarName...}


示例一:

interface IncludeFinalInterface{
    //接口中定义的变量都是public static final的
    int staticVar = 2009; //作为接口成员的变量,其赋值只能在声明中完成
}
class IncludeFinal{
    static final int staticVar;
    final int instanceVar;
   
    IncludeFinal(){
        instanceVar = 9; //实例变量的赋值还可以在构造器中进行
    }
    IncludeFinal(final boolean sameAsStatic){
        instanceVar = sameAsStatic ? staticVar : 9;
//      sameAsStatic = false;//不能编译,final修饰的构造器参数变量在构造器体中不能被再次赋值
    }
   
    static final void showStaticVar(){
        System.out.println("IncludeFinal.staticVar = " + staticVar);
    }
    final void showInstanceVar(){
        System.out.println("IncludeFinal.instatnceVar = " + instanceVar);
    }
    void show(final boolean showStatic){
        if( showStatic )
            showStaticVar();
        else
            showInstanceVar();
//      showStatic = false; //不能编译,final修饰的方法参数变量在方法体中不能被再次赋值
    }
    static void demoExceptionHandlerParameter(){
        try{
            System.out.println(10/0);
        }
        catch(final ArithmeticException ae){
            ae.printStackTrace();
//          ae = null;//不能编译,final修饰的异常处理器参数变量在catch语句块中不能被再次赋值
        }
    }
    static void showLocalVar(){
        final int localVar;
        localVar = 209; //局部变量在其值被访问之前必须被明确赋值,
                        //当然在其声明中同时指定一个初始化值似乎是一个更好的选择
        System.out.println("LocalVar = " + localVar);
    }
    static{ //除在声明中同时初始化外,作为类成员的静态变量,其赋值还可以在静态初始化块中进行
        staticVar = 2009;
    }
//  { //实例变量的赋值还可以在实例初始化块中进行
//      instanceVar = 9;
//  }
}
public class FinalTest extends IncludeFinal {
//  static void showStaticVar(){ //编译错误,不能重定义父类中用final修饰的静态方法
//      System.out.println("FinalTest.staticVar = " + staticVar);
//  }
//  void showInstanceVar(){ //编译错误,不能替换父类中用final修饰的实例方法
//      System.out.println("FinalTest.instatnceVar = " + instanceVar);
//  }  
    public static void main(String[] args){
        showStaticVar();
        demoExceptionHandlerParameter();
        showLocalVar();
        new IncludeFinal(false).show(false);
    }
}

二、关于final变量的进一步说明:

1)定义:blank final变量是指:其声明中不包含初始化表达式的final变量。
2)对于引用类型变量,final修饰符表示一旦赋值,该变量就始终指向堆中同一个对象,不可改变,但是其所指对象的状态是可以改变的
        这不象C++中的const,在Java中没有办法仅通过一个final就可声明一个对象的不变性(immutability)。
3)常变量(constant variable):
  ①定义:常变量是用“常量表达式”初始化的带有final修饰符的基本类型字符串类型变量,初始化发生在编译阶段;
  ②无论静态变量还是实例变量,如果它是常变量,则其引用在编译时会被替换成常变量的值,在class文件中对常变量的引用全部被变量值代替(相当于硬写);
            也正是基于此,当在源代码中修改某个常变量的初始值并重新编译后,该改动并不为其他class文件可见,除非对他们也重新编译。

4)用final修饰的参数变量,虽然并不为所有人喜欢,但它的确为编译器提供了附加的信息,一方面可以增强其错误检测能力,另一方面也有助于其对代码的优化。
5)final修饰符与其他修饰符共同出现时,书写顺序可参考下面一行:
  Annotation public protected privateabstract static final synchronized native transient volatilestrictfp

附注:有关编译时常量表达式的具体定义,可参考JLS中的相关章节(§15.28)。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值