java关键字final完全解析

来源:互联网 发布:java init和cinit 编辑:程序博客网 时间:2024/05/18 00:24

java关键字final完全总结

如有错误遗漏请指正,如需转载请注明出处

1.final修饰变量

final变量一旦显式初始化后,就不能再次赋值。

注意:

  1. final修饰的变量,无论是类变量、成员变量、局部变量还是形参,这些变量都需要进行显式初始化才能使用。final变量中保存的值不变。
    1. 对于final修饰的形参,在传递实参时就完成了显示初始化,很好理解。
    2. 对于final修饰的局部变量,和普通局部变量一样都需要显示初始化之后才能使用。因为java中局部变量没有隐式初始化。
    3. 对于final修饰的成员变量,必须在声明final成员变量时显示初始化,或在动态代码块或在构造函数中初始化,不然报错。
    4. 对于final修饰的类变量,必须声明final类变量时显式初始化,或在静态代码块中显式初始化,不然报错。
    5. 空白final(blank final),所有的为初始化的final局部变量,隐式初始化的final成员变量 final类变量都是blank final 变量,必须显示初始化之后才能使用。
    6. final变量中保存的值不能变化,但不表示对象不能变化。对于基本数据类型,变量中直接保存的就是基本类型的具体值,不变就不变了。但对于引用类型(对象 数组),变量中保存的是对象的地址,变量中的值不变,表示地址不变,表示该变量始终指向一个对象,但我们可以改变对象的状态(对象的属性)。但要注意java中的不可变类型(Immutable Objects),例如Integer Long等基本类型包装类,String等的都是不可变类型,不可变类型的对象是不可变的。
  2. final修饰变量后导致的“宏替换”问题

    计算机科学里的宏(Macro),是一种批量处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串)。

    c里面的宏:
    格式: #define PI 3.1415926

    作用:在预编译时把源码中的所有PI换成3.1415926

    java里面的宏:
    条件:

    1. final变量且声明时同时显式初始化
    2. 变量必须是String或基本数据类型
      作用:在编译期把变量替换为具体的值。

      package com.wzm;  /** * @author 王宗明* @version 创建时间:2017年1月9日 下午5:10:34 * 程序的简单说明 */public class TestFinal {    public void add(){        int a=1;        int b=1;        int c=a+b;    }    public static void main(String[] args) {        final int a=1;        final int b=1;        int c=a+b;//等价于 c=1+1;因为发生了宏替换,a替换成了1,b也替换成了1。    }}

      查看TestFinal的字节码可以发现确实发生了宏替换。
      下面给出了add方法和main方法的部分字节码,因为我们也只关注这部分

      .......public void add();descriptor: ()Vflags: ACC_PUBLICCode:  stack=2, locals=4, args_size=1     0: iconst_1     1: istore_1     2: iconst_1     3: istore_2     4: iload_1     5: iload_2     6: iadd     7: istore_3     8: return.......public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:    stack=1, locals=4, args_size=1     0: iconst_1     1: istore_1     2: iconst_1     3: istore_2     4: iconst_2     5: istore_3     6: return.......

2.final修饰方法

final修饰方法表示”最终”方法,子类不能重写父类的final方法。

但是我们需要注意的一点是:因为重写的前提是子类可以从父类中继承此方法,如果父类中final修饰的方法同时访问控制权限为private,
将会导致子类中不能直接继承到此方法,因此,此时可以在子类中定义相同的方法名和参数,此时不再产生重写与final的矛盾,而是
在子类中重新定义了新的方法。

public class Child extends Parent {    public void getName(){    }}class Parent {    /**    * 因为private修饰,子类中不能继承到此方法,因此,子类中的getName方法是重新定义的、    * 属于子类本身的方法,编译正常    */     private final void getName(){    }    // 因为pblic修饰,子类可以继承到此方法,子类中不能重写这个方法,否则编译出错    public final void getAge(){    }}

3.final修饰类

final修饰类表示”最终类”,final类不能被继承,即final类不能有子类。

0 0
原创粉丝点击