知识回顾——final关键字

发布时间 2023-04-06 20:12:03作者: StormArcita

一.什么时候使用final关键字

  1.被final修饰的类不能被继承,所以当我们希望某类不能被继承时,就是用final修饰此类。

  2.当不希望父类的某个方法不被子类覆写(Override),可以用final修饰此方法。

  3.当不希望类的某个属性的值被修改,可以用final修饰。

  4.当不希望某个局部变量被修改,可以用final修饰,变为局部常量。

二.final使用注意事项和细节讨论

  1.final修饰的属性又叫常量,一般使用XX_XX_XX命名。

  2.final修饰的属性在定义时,必须赋初值,并且以后不能再修改,赋值可以加在如下位置之一:

    1)定义时:如 public final double TAX_RATE = 0.08;

    2)在构造器中

    3)在代码块中

class Dog{
    //定义时赋初值
    public final String NAME1 = "name1";
    public final String NAME2;
    public final String NAME3;
    
    //构造方法中赋初值
    public Dog(){
        NAME2 = "name2";
    }

    //代码块中赋初值
    {
        NAME3 = "name3";
    }
}

  3.如果final修饰的属性是静态的,则初始化的位置只能是:

    1)定义时

    2)在静态代码块

    不能在构造器中赋值。

class fish{
    //定义时赋初值
    public static final int AGE1 = 11;
    public static final int AGE2;
    
    //静态代码块中赋初值
    static{
        AGE2 = 12;
    }
}

    为什么final修饰的属性是静态的,只能在定义时和静态代码块中赋初值,而不能在构造方法中赋初值?

    因为在类加载的时候,被static修饰的属性、方法和代码块就会初始化,而类加载时不会调用构造方法,如果被final修饰的静态属性可以在构造方法中赋初值,就会导致类加载时该属性没有初值,这与final“必须赋初值”是冲突的。

  4.final类不能继承,但是可以实例化对象。

  5.如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承,仍然遵守继承机制。

class BB{
    public final void test(){
        System.out.println("我是父类被final修饰的方法");
    }
}

class CC extends BB{

}

public class final_test {
    public static void main(String[] args) {
    CC c = new CC();
    c.test();//输出“我是父类被final修饰的方法”
    }
}

   6.一般来说,如果一个类已经是final类了,就没有必要再将其中的方法修饰为final方法了。因为一个方法加final的目的就是为了让继承类不能再重写此方法,如果类上加了final,代表此类不能被继承,继承都不能继承了,何谈其中的方法被重写?多此一举。

   7.final不能修饰构造方法(构造器)。

   8.final和static往往搭配使用,效率更高,不会导致类加载,底层编译期做了优化。

    什么意思?请看代码:

public class final_test_02 {
    public static void main(String[] args) {
        System.out.println(DD.num);
  } }
class DD{
  //static和final不连用的情况:
public static int num = 999; static{ System.out.println("我是DD中static代码块中的输出语句"); } }

    输出:

      我是DD中static代码块中的输出语句
      999

public class final_test_02 {
    public static void main(String[] args) {
        System.out.println(DD.num);
  }
}

class DD{
  //static和final不连用的情况:
    public static int NUM = 999;
    static{
        System.out.println("我是DD中static代码块中的输出语句");
    }
}

    输出:

      999

    当我们不将static和final连用时,若想直接调用num属性,需要先加载类,而类加载时就会加载静态属性、方法和代码块,所以static代码块中的输出语句也会一并输出。

    而将static和final连用时,若想直接调用NUM属性,不会发生类加载,只会拿出NUM属性,所以只输出999。

   

    9.包装类(Integer、Double、Float、Boolean、String等)是final类,被final修饰,不能被继承。