JAVA中的修饰变量final

在Java中,`final` 关键字是一个非常重要的修饰符,它用于表示一个变量、方法或类是不可变的。当`final`用于变量时,它意味着这个变量的值一旦被初始化之后就不能被改变。这对于定义常量非常有用,因为它确保了变量在整个程序运行期间都保持其初始值不变。

final 变量的基本用法

在Java中,`final` 变量可以是基本数据类型的变量,也可以是引用类型的变量。但是,当`final`用于引用类型的变量时,它指的是引用本身是不可变的,而不是对象本身不可变。也就是说,你不能让`final`引用指向另一个对象,但是你可以修改该对象内部的状态(如果对象是可变的)。

示例代码

java 复制代码
public class FinalExample {
    // final 修饰的基本数据类型变量
    final int MAX_VALUE = 100; // MAX_VALUE的值被初始化为100,之后不能被修改

    // final 修饰的引用类型变量
    final String NAME = "Java"; // NAME的引用指向"Java"字符串,之后NAME不能指向另一个字符串

    public static void main(String[] args) {
        // 尝试修改final变量的值,会编译错误
        // MAX_VALUE = 200; // 编译错误

        // 尝试让final引用指向另一个对象,会编译错误
        // NAME = "Python"; // 编译错误

        // 但是,如果对象是可变的,我们可以修改对象内部的状态
        // 假设我们有一个可变的Person类
        final Person person = new Person("Alice", 25);
        // 下面的操作是合法的,因为我们没有改变person的引用,只是修改了对象的状态
        person.setName("Bob");

        // 打印修改后的信息
        System.out.println(person.getName()); // 输出: Bob
    }

    // 假设的Person类
    static class Person {
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        // ... 其他方法
    }
}

final 变量的初始化

`final` 变量必须在声明时或者在构造器中初始化。对于类的成员变量,如果`final`变量没有在声明时初始化,那么它必须在每个构造器中初始化。

示例代码

java 复制代码
public class FinalInitialization {
    // 在声明时初始化
    final int constantValue = 42;

    // 引用类型也可以在声明时初始化
    final String greeting = "Hello, World!";

    // 类的成员变量,在构造器中初始化
    final int value;

    // 无参构造器
    public FinalInitialization() {
        // 必须在这里初始化value
        value = 10;
    }

    // 带参构造器
    public FinalInitialization(int initialValue) {
        // 也可以在这里初始化value
        value = initialValue;
    }

    public static void main(String[] args) {
        FinalInitialization obj1 = new FinalInitialization();
        FinalInitialization obj2 = new FinalInitialization(20);

        System.out.println(obj1.value); // 输出: 10
        System.out.println(obj2.value); // 输出: 20
    }
}

final 变量的注意事项

  • 初始化时机:`final` 变量必须在声明时或者在构造器中初始化。
  • 空白`final`:如果`final`变量在声明时没有初始化,那么它就是一个空白`final`变量,必须在构造器中初始化。
  • 引用与对象:当`final`用于引用类型的变量时,它指的是引用本身是不可变的,而不是对象本身不可变。这意味着你不能将`final`引用指向另一个对象,但是你可以修改该对象内部的状态(如果对象是可变的)。
  • 不可变性:在Java中,如果一个类的所有成员变量都是`final`的,那么这个类通常设计成不可变的(immutable)。不可变对象一旦创建,其状态就不能被改变,这样的对象是线程安全的。

final 变量的作用

    1. 定义常量:`final` 变量通常用于定义常量,比如数学中的π(π)值、物理中的光速等。
    1. 提高安全性:通过防止变量被意外修改,`final` 变量可以提高代码的安全性和稳定性。
    1. 提升性能:在某些情况下,编译器可以通过优化`final`变量来提高程序的性能,因为`final`变量的值在编译时就是已知的。
    1. 设计不可变对象:通过将所有成员变量都声明为`final`,可以设计不可变对象,这样的对象一旦创建,其状态就不能被改变。
    1. 多线程安全:在多线程编程中,使用`final`关键字可以确保共享数据的不可变性,从而避免并发问题。

示例代码 - 使用final设计不可变类

java 复制代码
public class ImmutablePerson {
    // 使用final修饰符来声明成员变量为常量
    private final String name;
    private final int age;
    private final String address;
  
    public ImmutablePerson(String name, int age, String address) {
        this.name = name; // 由于是final的,这里的赋值操作不能再改变name的值了
        this.age = age; // 同上对于age和address来说也是一样的情况
        this.address = address; // final引用指向的内容不能再改变,但是可以修改引用的对象里的可变的属性值(如String里的value)
    }
  
    // getter方法略...
  }

注意: `String`类是不可变的,所以虽然我们使用了 `address` 的引用初始化了一个 `String`,但是我们无法去改变这个 `String` 的值,因为它是不可变的,这也就是为什么我们说这个 `ImmutablePerson` 是不可变的了,因为他的所有属性都是不可变的,所以这个类的实例也是不可变的。

相关推荐
晴子呀2 分钟前
Spring底层原理大致脉络
java·后端·spring
DreamByte4 分钟前
Python Tkinter小程序
开发语言·python·小程序
只吹45°风9 分钟前
Java-ArrayList和LinkedList区别
java·arraylist·linkedlist·区别
覆水难收呀12 分钟前
三、(JS)JS中常见的表单事件
开发语言·前端·javascript
阿华的代码王国16 分钟前
【JavaEE】多线程编程引入——认识Thread类
java·开发语言·数据结构·mysql·java-ee
黑蛋同志16 分钟前
array和linked list的区别
java
繁依Fanyi22 分钟前
828 华为云征文|华为 Flexus 云服务器部署 RustDesk Server,打造自己的远程桌面服务器
运维·服务器·开发语言·人工智能·pytorch·华为·华为云
andrew_121922 分钟前
腾讯 IEG 游戏前沿技术 一面复盘
java·redis·sql·面试
andrew_121925 分钟前
腾讯 IEG 游戏前沿技术 二面复盘
后端·sql·面试
寻求出路的程序媛30 分钟前
JVM —— 类加载器的分类,双亲委派机制
java·jvm·面试