JAVA中final关键字的作用

final关键字的功能概述

  在Java中,关键字 final 的意思是终态,可以用于声明变量、方法和类,分别表示变量不可变,方法不可被覆盖,类不可被继承。下面进行详细阐述。

1、用来修饰变量

  当使用final修饰一个变量(属性)时,这个属性就成为一个常量。此时可以考虑赋值的位置有直接初始化、代码块中初始化和构造器中初始化。

final修饰局部变量

  使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参以后,就只能在方法体内使用此形参,而不能重新赋值。形参是局部变量,其作用域是整个方法体。

public void localArg(final int arg){
    arg = 20;//编译不通过,异常信息【Cannot assign a value to final variable 'arg'】
    System.out.println(arg);
}
public void localArg(){
    final int ARG = 10;//常量,基本类型变量
    ARG += 20;//编译不通过
}

final关键字修饰成员变量

  对于成员变量来说,一旦使用final关键字,也是不能再次改变。
  和局部变量的不同点在于,成员变量需要有默认值,因此必须手动赋值。final修饰的成员变量赋值途径有两个,而且只能二者选择其一:①在定义的时候直接赋值,②在构造方法体里面赋值,此时必须保证所有重载的构造方法都对final修饰的成员变量赋值。

public User(Long id, int age, String name) {
    super();
    this.id = id;
    this.age = age;
    this.name = name;
    var = 91;
}

//定义时直接赋值
private final int a = 32;
//使用构造方法赋值
private final int var;
public User() {
    var = 90;
}

final修饰基本类型变量

  当使用final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。上文中的int ARG就属于基本类型变量。

final修饰引用类型变量

  当使用final修饰引用类型变量时,比如对象和数组等,不可变的含义就是地址值不能改变,但是该地址指向的对象的内容是可以改变的。它保存的仅仅是一个引用,final只能保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以改变。
  这里引用一个网上常见的例子,以说明final修饰基本类型变量和引用类型变量的区别。

//final修饰基本类型变量和引用类型变量的区别
import java.util.Arrays;
class Person
{
    private int age;
    public Person(){}
   // 有参数的构造器
    public Person(int age)  {
        this.age = age;
    }
    public void setAge(int age){this.age = age;}
    public int getAge(){return age;}
}
public class FinalReferenceTest {
    public static void main(String[] args)  {
        //final修饰数组,iArr是一个引用变量
        final int[] iArr = {5,6,12,19};
        System.out.println(Arrays.toString(iArr));
        //对数组元素排序,合法
        Arrays.sort(iArr);
        System.out.println(Arrays.toString(iArr));
        //对数组元素赋值,合法
        iArr[2] = -8;
        System.out.println(Arrays.toString(iArr));
        Arrays.sort(iArr);
        System.out.println(Arrays.toString(iArr));
        //下面语句对iArr重新赋值,非法
        //iArr = null;


        //final修饰Person变量,p是一个引用变量
        final Person p = new Person(45);
        //改变Person对象的age实例变量,合法
        p.setAge(23);
        System.out.println(p.getAge());
        //下面语句对p重新赋值,非法
        //p = null;
    }
}

2.用来修饰方法

  当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。例如Object类中的getClass()方法。使用IDEA,在User类中重写 Object类中的getClass()方法,则可以看到如下异常信息,提示方法无法被子类重写。

'getClass()' cannot override 'getClass()' in 'java.lang.Object'; overridden method is final

  在java中,把一个类中的方法修饰为final,意味着两个功能,第一点是该方法不能被重载,第二点是允许编译器将所有对此方法的调用转化为inline(行内)调用的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高。第二点也同时提醒我们,要谨慎的将方法定义为final,因为如果方法很庞大,你的代码量就会因为inline而迅速膨胀,可能反而会影响效率。

3.用来修饰类

  当用final修改类时,该类成为最终类,无法被继承。简称为“断子绝孙类”。

/***
* final用法3:修饰类,则该类成为最终类,无法被继承 
*下面这行代码放开注释,就会抛出异常提示
*/
//class MyString extends String{}

  比如常用的String类、System类、StringBuffer类,它们都是最终类。定义断子绝孙类的目的是提高安全性,增强程序的可读性。
  老铁们, 因个人能力有限,难免有瑕疵,如果发现bug或者有更好的建议,那么请在文章下方留言!

原文地址:https://www.cnblogs.com/east7/p/13939379.html