zoukankan      html  css  js  c++  java
  • java final修饰符

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

    1)用final修饰的类不能被扩展,也就是说不可能有子类;
    2)用final修饰的方法不能被替换或隐藏:
      ①使用final修饰的实例方法在其所属类的子类中不能被替换(overridden);
      ②使用final修饰的静态方法在其所属类的子类中不能被重定义(redefined)而隐藏(hidden);
    3)用final修饰的变量最多只能赋值一次,在赋值方式上不同类型的变量或稍有不同:
      ①静态变量必须明确赋值一次(不能只使用类型缺省值);作为类成员的静态变量,赋值可以在其声明
       中通过初始化表达式完成,也可以在静态初始化块中进行;作为接口成员的静态变量,赋值只能在其
       声明中通过初始化表达式完成;
      ②实例变量同样必须明确赋值一次(不能只使用类型缺省值);赋值可以在其声明中通过初始化表达式
       完成,也可以在实例初始化块或构造器中进行;
      ③方法参数变量在方法被调用时创建,同时被初始化为对应实参值,终止于方法体(body)结束,在此
       期间其值不能改变;
      ④构造器参数变量在构造器被调用(通过实例创建表达式或显示的构造器调用)时创建,同时被初始化
       为对应实参值,终止于构造器体结束,在此期间其值不能改变;
      ⑤异常处理器参数变量在有异常被try语句的catch子句捕捉到时创建,同时被初始化为实际的异常对象
       ,终止于catch语句块结束,在此期间其值不能改变;
      ⑥局部变量在其值被访问之前必须被明确赋值;

    示例一:
    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);
        }
    }
    运行结果:
    IncludeFinal.staticVar = 2009
    java.lang.ArithmeticException: / by zero
        at IncludeFinal.demoExceptionHandlerParameter(FinalTest.java:32)
        at FinalTest.main(FinalTest.java:61)
    LocalVar = 209
    IncludeFinal.instatnceVar = 9

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

    1)定义:blank final变量是其声明中不包含初始化表达式的final变量。
    2)对于引用类型变量,final修饰符表示一旦赋值该变量就始终指向堆中同一个对象,不可改变,但是其
      所指对象本身(其状态)是可以改变的;不象C++中的const,在Java中没有办法仅通过一个final就可
      声明一个对象的不变性(immutability)。
    3)常变量(constant variable):
      ①定义:常变量是用编译时常量表达式初始化的带有final修饰符的基本类型或字符串类型变量;
      ②无论静态变量还是实例变量,如果它是常变量,则其引用在编译时会被解析成该常变量所表示的值,
       在class文件中并不存在任何对常变量域的引用;也正是基于此,当在源代码中修改某个常变量域的
       初始值并重新编译后,该改动并不为其他class文件可见,除非对他们也重新编译。
    示例二:
    public class ConstantVariable {
        static final int staticVar = 10 + 8; //静态变量staticVar是一个常变量
        final int instanceVar =  100 + 8; //实例变量instanceVar也是一个常变量
        //静态变量notConstantVariable不是常变量,因为其初始化表达式不是编译时常量表达式
        static final int notConstantVariable = (int)(Math.random() * 10);
    }
    public class Test {
        public static void main(String[] args){
            //对类ConstantVariable中常变量staticVar的引用
            System.out.println("staticVar = " + ConstantVariable.staticVar);
            //对类ConstantVariable中常变量instanceVar的引用
            System.out.println("instanceVar = " + new ConstantVariable().instanceVar);
            //对类ConstantVariable中静态变量notConstantVariable的引用
            System.out.println("notConstantVariable = " + ConstantVariable.notConstantVariable);
        }
    }
    运行结果:
    staticVar = 18
    instanceVar = 108
    notConstantVariable = 2
    Test.class文件的反编译结果:
    import java.io.PrintStream;
    public class Test
    {   //从该文件很容易验证,当在ConstantVariable.java中修改常变量的值并重新编译后,类Test的运行结果不会受任何影
      //响
    ,除非把Test.java文件也重新编译一遍
        public Test(){}
        public static void main(String args[]){
            //对常变量ConstantVariable.staticVar的引用在编译后直接被其值“18”替换

        System.out.println("staticVar = 18"); 
            (new ConstantVariable()).getClass();
            //对类ConstantVariable中常变量instanceVar的引用在编译后直接被其值“108”替换
            System.out.println((new StringBuilder("instanceVar = ")).append(108).toString());
            //ConstantVariable.notConstantVariable不是常变量,所以其引用得以保持
            System.out.println(
                (new StringBuilder("notConstantVariable = ")).
                append(ConstantVariable.notConstantVariable).

                toString()

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

  • 相关阅读:
    CentOS升级参考
    CentOS下配置VNC
    CentOS SSH安全和配置无密码登录
    kubernetes使用本地仓库
    IdentityServer4入门五:错误处理
    IdentityServer4入门四:应用Implicit模式保护网站(下)
    IdentityServer4入门四:应用Implicit模式保护网站(上)
    IdentityServer4入门三:授权模式
    浅谈欧几里得算法求最大公约数(GCD)的原理及简单应用
    [CodePlus 2017 11月赛]晨跑 题解(辗转相除法求GCD)
  • 原文地址:https://www.cnblogs.com/chen-jack/p/7923338.html
Copyright © 2011-2022 走看看