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` 是不可变的了,因为他的所有属性都是不可变的,所以这个类的实例也是不可变的。

相关推荐
Cosmoshhhyyy3 小时前
《Effective Java》解读第54条:返回零长度的数组或者集合,而不是null
java·开发语言·python
沐一的blog3 小时前
Java 并发 100 问:从面试到生产(二)
后端·面试
jsl_jsl_jsl3 小时前
☕ Java 高并发进阶(二):无锁并发与数据隔离——CAS、Unsafe 与 ThreadLocal 深度内核解密
java
kTR2hD1qb3 小时前
Keepalived 学习总结
java·服务器·学习
用户713874229003 小时前
ASP.NET Core .NET 10 错误响应体系全景:从 BadRequest 到编译器基础设施
后端
土狗TuGou3 小时前
SQL内功笔记 · 第9篇:UPDATE FROM 进阶——告别逐行子查询,拥抱集合更新
java·数据库·笔记·sql·mysql
程序员cxuan3 小时前
MiniMax M3 发布,据说接近 Opus 4.7?真的假的
人工智能·后端·程序员
Gopher_HBo3 小时前
Go语言学习笔记(三)复杂数据类型channel和自定义结构
后端
小谢小哥3 小时前
63-Gradle构建详解
java·后端·架构
Sam_Deep_Thinking3 小时前
一个业务场景只需要一个ThreadLocal实例
java·面试