final关键字细节

  final关键字在java中是一个很重要的关键字,其实按照其字面意思理解,就可以一窥这个关键字端倪,final的本意是最终的。所谓最终的,其最重要的特征就是不能修改,由此衍生出的许多细节均应以这个特征作为基础。

  final可以修饰类、方法、变量。变量包括成员变量和局部变量。

  1.修饰类

  final修饰过的类不能被继承,如下的代码在ide中是会报错的。

  

final class Father{
    
}
//The type son cannot subclass the final class Father
class son extends Father{
    
}

  2.修饰方法

  final关键字修饰过的方法不能被子类重写。

  

class Father {
    public final void father_func() {
        System.out.println("father function");
    }

}
class son extends Father {
    //Cannot override the final method from Father
    public void father_func() {

    }
}

  其实不管是final修饰的类不能被继承,还是final修饰的方法不能被子类重写,都是要保证这个类,这个方法时最终的,不能再被更改。这也符合final的本意。

  3.修饰成员变量

  final修饰的成员变量只能被赋值一次,而且必须在声明的同时或者构造函数中显式赋值,然后才能使用。否则ide会给出提醒。因为不像普通的成员变量,即便不显式初始化,系统也会默认初始化。

  以下代码会出错。

public class FinalDemo {
    final Father f;
    //The blank final field f may not have been initialized
    public FinalDemo(){
        
    }
    public static void main(String args[]) {

    }

}

class Father {
    public final void father_func() {
        System.out.println("father function");
    }

}

  这样写才正确 

public class FinalDemo {
    final Father f;
    public FinalDemo(){
        f=new Father();
    }
    public static void main(String args[]) {

    }

}

  4.修饰局部变量

  final修饰的局部变量只能被赋值一次。有时候我们方法的形式参数(这也相当于一个局部变量)用final 来声明,目的就是告诉编程的人,不要再在方法体里面给这个变量去赋值了

  如下代码是错误的。

class Father {
    public void func(final int y){
        //The final local variable y cannot be assigned. It must be blank and not using a compound assignment
        y=3;
        System.out.println(y);
    }

}

  既然y被final修饰,它就不能在方法体中继续赋值。修改成如下,并调用才是正确的。

  

public class FinalDemo {
    public static void main(String args[]) {
        Father f=new Father();
        f.func(1);
        f.func(3);
    }

}

class Father {
    public void func(final int y){
        System.out.println(y);
    }

}

  上述执行的结果是1和3。两次调用func,分别传入1和3给final形参y。此处不要认为我修改了y的值,我调用了两次func方法,两次的局部变量并不是同一个。所以不存在重复赋值的说法。

  如果在方法体中定义一个final类型的局部变量,则只能给他赋值一次,不能重复赋值,这很好理解。当然也不能不赋值,这是最基本的,方法体中不管是不是final修饰的局部变量,都应该先被赋值才能使用。

  5.如果一个类中的成员变量,除了用final修饰,还加上了static,那么他就有两层的属性,首先是静态的,可以直接通过类名直接访问得到。其次它是不可再被修改的。那么这种类型的变量我们可以称之为静态常量,它必须在声明的时候就直接显式初始化,即便在构造函数中都不能再初始化(可以理解为静态变量并不需要实例化就可以访问到,所以有可能不会执行到构造函数里面的代码,这就无法保证这个final变量一定会被初始化,于是干脆在声明的时候就初始化,最为保险)

  这种静态常量可以直接通过类名来访问,当我们再加上一个访问权限修饰符,比如public以后,这就成为了一个全局的常量,在整个项目中都能被访问到。在项目中,我们经常在一个类中写满了public static final类型的变量,并且命名为constant.java。然后通过constant.x来获取这些常量。

  

  

原文地址:https://www.cnblogs.com/roy-blog/p/7670327.html