Bootstrap

Java中的关键字之final详解

目录

final关键字定义与作用

修饰变量

修饰成员变量

修饰局部变量

修饰基本类型变量和引用类型变量的区别

修饰方法

修饰类


final关键字定义与作用

在java中,关键字用于确保其修饰的类、方法或变量不可被改变。具体来说:

  • 修饰变量:当一个变量被声明为final时,意味着这个变量的值在初始化后就不能被修改。这包括成员变量(类变量和实例变量)、局部变量和形参。final变量必须在声明时或构造函数中初始化,之后就不能再被赋值。

  • 修饰方法:如果一个方法被声明为final,那么这个方法就不能被子类重写。这通常用于那些在父类中已经实现了最终逻辑,不希望子类修改的方法。

  • 修饰类:当一个类被声明为final,那么这个类就不能被继承。这通常用于那些设计为不应该被修改或扩展的类,如Java中的String类。

使用final关键字的作用包括:

  • 提高安全性:通过防止变量、方法和类的继承或重写,确保代码的稳定性和正确性。
  • 优化性能:编译器可以对final变量进行优化处理,如直接替换常量值到代码中,减少运行时的开销。
  • 增强代码可读性和可维护性:通过明确标识不应被修改的元素,使代码更易于理解和维护。

总之,final关键字是Java中一个重要的工具,用于确保代码的安全性和稳定性,同时也提高了代码的可读性和可维护性。

修饰变量

修饰成员变量

当我们使用final修饰变量时,必须赋予初始值。指定初始值的地方如下:

  • 类变量:必须在静态初始化块中指定初始值或声明该类变量时指定初始值,而且只能在这两个地方的其中之一指定。
  • 成员变量:必须在普通初始化块、声明该实例变量或构造器中指定初始值,而且只能在三个地方的其中之一指定。
public class Class1 {
    // 定义成员变量时直接赋值
    final int a=0;
    final String b;
    final int c;
    final static double d;
    //对于被final修饰的没有初始值的类变量,必须在静态初始化代码块中赋值
    static {
        d=0.1;
    }
    //被final修饰的没有初始值的成员变量可以在初始化代码块中赋值
    {
        b="acd";
    }
    //被final修饰的没有初始值的成员变量还可以在构造函数中赋值
    public Class1(int c) {
        // b c 在之前都已经被赋值过了,因此,构造函数中无法对这两个数据进行操作
        this.c = c;
    }
}

修饰局部变量

系统不会对局部变量进行初始化,局部变量必须被显示初始化。因此使用final修饰局部变量时,即可以在定义时指定默认值,也可以不指定默认值。如果在定义时没有指定默认值,则可以在后面代码中对该final变量赋初始值,但只能一次,不能重复赋值;如果在定义时已经指定默认值,则后面代码中不能再对该变量赋值。

    public static void main(String[] args) {
        final int a=10;
        final double b;
        b=10;
        b=11;
        System.out.println(b);
    }

 运行结果:

会报错,b第一次赋值之后就不可以继续赋值了。

修饰基本类型变量和引用类型变量的区别

当使用final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。但对于引用类型变量而言,它保存的仅仅是一个引用,final只保证这个引用变量所引用的地址不会改变,即一直引用同一个对象,但可以改变引用类型变量所引用的对象的内容。

class Cat{
    private String name;

    public Cat(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Class2 {
    public static void main(String[] args) {
        // 创建了3个对象,一个数组对象一个int,一个自定义的cat
        // 其中 数组和cat时引用类型,而int是基本类型
        final int [] arr=new int[]{1,2,3,4,5};
        final int a=10;
        final Cat cat=new Cat("mimi");
        System.out.println(Arrays.toString(arr));
        System.out.println(cat.getName());
        arr[3]=10;
        cat.setName("huahua");
        System.out.println(Arrays.toString(arr));
        System.out.println(cat.getName());
    }
}

 运行结果:

修饰方法

 final修饰的方法不可被重写,如果出于某些原因,不希望子类重写父类某个方法,则可以使用final修饰该方法。Java提供的Object类里就有一个final方法:getClass(),因为Java不希望任何类重写这个方法,所以使用final把这个方法密封起来。但对于该类提供的toStirng()和equals()方法,都允许子类重写,因此没有使用final修饰他们。

修饰类

final修饰的类不可以有子类,例如java.lang.String类就是一个final类,他不可以有子类。

当子类继承父类时,将可以访问到父类内部数据,并可以通过重写父类方法来改变父类方法的实现细节,这可能导致一些不安全的因素。为了保证某个类不可被继承,则可以使用final修饰这个类。

因此抽象类肯定就不可能被final修饰,不然一点意义没有,直接用final修饰,会直接报错。

;