Java中不可变对象(Immutable Objects)的使用

 更新时间:2025年08月18日 09:51:34   作者:swadian2008  
不可变对象创建后不可更改,Java中如String、Integer等基本类型包装类及LocalDate等日期时间类,下面就来详细的介绍一下,感兴趣的可以了解一下

1、什么是Immutable Objects?

不可变对象指的是在创建之后,它们的值无法被修改的对象。这意味着如果想改变一个不可变对象的值,就需要创建一个新的对象。

在许多编程语言中,字符串和数字都是不可变的对象。例如,在 Python 中,字符串就是不可变的,因此不能像下面这样改变字符串的值:

string = "hello"
string[0] = "H" # This will raise an error

相反,你需要创建一个新的字符串对象:

new_string = "H" + string[1:]

这个新字符串就是一个全新的字符串对象,和原来的字符串对象没有关系。

不可变对象的一个好处是它们更容易被并发程序安全地使用。因为不可变对象是无法修改的,所以不需要担心在多线程环境下出现竞态条件的问题。

此外,不可变对象也更容易进行缓存和复用。因为不可变对象的值不会改变,所以你可以安全地将它们存储在缓存中,并在需要时直接使用它们,而不需要重新计算。

所以,合理的使用不可变对象可以提高程序的安全性、并发性能和效率。

2、Java 中有哪些不可变的对象?

Java中有许多不可变的对象,以下是其中的一些:

  1. 字符串(String):字符串在Java中是不可变的对象。一旦创建了一个字符串对象,它的值就不能被修改。
  2. 整数(Integer)、长整数(Long)、浮点数(Float)和双精度浮点数(Double):这些数字类型在Java中也是不可变的对象。一旦创建了一个数字对象,它的值就不能被修改。
  3. 枚举(Enum):枚举类型也是不可变的对象。枚举类型中的每个元素都是一个不可变的对象。
  4. LocalDate、LocalTime、LocalDateTime:Java 8中的日期和时间API中的这些类也是不可变的对象。一旦创建了一个日期或时间对象,它的值就不能被修改。
  5. BigInteger、BigDecimal:这些类提供了任意精度的整数和浮点数运算,也是不可变的对象。

需要注意的是,虽然以上对象的值不能被修改,但是它们的引用可以被修改。这意味着,可以创建新的对象来代替旧的对象,但是旧的对象本身的值不会被修改。

3、不可变对象在JVM中的存储

Java中不可变对象通常存在JVM的方法区(Method Area)或者叫做永久代(PermGen)中。方法区是JVM中的一块内存区域,用于存储类的信息、静态变量、常量池、方法代码等。永久代是方法区的一个实现,用于存储静态文件、类文件信息、字节码、常量池等内容,它在Java 8之后被元空间(Metaspace)所取代。// 存储在方法区中的常量池里

不可变对象通常在JVM启动时被加载并存储在方法区或永久代中,因为它们的值是不可变的,所以可以被安全地共享和重用。同时,这些对象在JVM生命周期内只需要被创建一次,因此它们的存储位置也通常是固定的。

需要注意的是,如果使用字符串常量或常量表达式创建不可变对象,这些对象也可能存储在JVM的常量池中。常量池是方法区的一部分,用于存储字符串常量、基本类型常量等。由于常量池中的字符串常量是不可变的,因此它们也被认为是不可变对象。

4、在 Java 中定义Immutable Objects的方式有哪些?

在 Java 中,有多种方式可以定义不可变对象。以下是几种常见的方式:

  • 声明类为 final:通过将类声明为 final 类型,可以确保该类不能被继承和修改。这样可以确保不会发生对象状态的改变。例如:// 不允许子类重写方法。最简单的就是将类声明为final。
public final class ImmutableClass {
    // ...
}
  • 将所有字段设置为 final 和 private:通过将类的成员变量声明为 final,可以确保这些变量在对象创建后不能被修改。例如:
public final class Person {
    private final String name;
    private final int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
  • 不提供 setter 方法:通过只提供 getter 方法,而不提供 setter 方法,可以确保对象的状态不能被修改。例如:
public final 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 int getAge() {
        return age;
    }
}
  • 构造对象时赋值:通过在构造函数中初始化对象的成员变量,可以确保对象创建后它们的值不会改变。示例同上。
  • 使用不可变集合类:Java 中的 Collections 类提供了一些不可变的集合类,如 Collections.unmodifiableList 和 Collections.unmodifiableMap,它们可以确保集合内容在对象创建后不能被修改。例如:
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");

List<String> immutableList = Collections.unmodifiableList(list);

以上是一些在 Java 中定义不可变对象的方式,这些方式可以单独使用,也可以结合使用,以创建更加严格的不可变对象。// 在并发程序中作为锁的对象应该是不可变对象。

到此这篇关于Java中不可变对象(Immutable Objects)的使用的文章就介绍到这了,更多相关Java 不可变对象内容请搜索脚本之家以前的文章或继续浏览下

相关文章

  • springboot整合redis过期key监听实现订单过期的项目实践

    springboot整合redis过期key监听实现订单过期的项目实践

    现在各种电商平台都有自己的订单过期时间设置,那么如何设置订单时间过期呢,本文主要介绍了springboot整合redis过期key监听实现订单过期的项目实践,感兴趣的可以了解一下
    2023-12-12
  • maven无法依赖spring-cloud-stater-zipkin的解决方案

    maven无法依赖spring-cloud-stater-zipkin的解决方案

    这篇文章主要介绍了maven无法依赖spring-cloud-stater-zipkin如何解决,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-05-05
  • Java通过反射,如何动态修改注解的某个属性值

    Java通过反射,如何动态修改注解的某个属性值

    这篇文章主要介绍了Java通过反射,动态修改注解的某个属性值操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • ActiveMQ持久化机制代码实例

    ActiveMQ持久化机制代码实例

    这篇文章主要介绍了ActiveMQ持久化机制代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • springboot如何使用yml文件方式配置shardingsphere

    springboot如何使用yml文件方式配置shardingsphere

    这篇文章主要介绍了springboot如何使用yml文件方式配置shardingsphere问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Java数组转换为集合的相关方法

    Java数组转换为集合的相关方法

    在Java中我们经常需要将数组从一种类型转换为另一种类型,下面这篇文章主要给大家介绍了关于Java数组转换为集合的相关方法,文中通过图文及代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • IntelliJ IDEA连接MySQL数据库详细图解

    IntelliJ IDEA连接MySQL数据库详细图解

    今天小编就为大家分享一篇关于intellij idea连接mysql数据库详细图解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • 轻松掌握Java观察者模式

    轻松掌握Java观察者模式

    这篇文章主要帮助大家轻松掌握Java观察者模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • Java多线程并发编程 Volatile关键字

    Java多线程并发编程 Volatile关键字

    volatile 关键字是一个神秘的关键字,也许在 J2EE 上的 JAVA 程序员会了解多一点,但在 Android 上的 JAVA 程序员大多不了解这个关键字。只要稍了解不当就好容易导致一些并发上的错误发生,例如好多人把 volatile 理解成变量的锁
    2017-05-05
  • 基于FeignClient调用超时的处理方案

    基于FeignClient调用超时的处理方案

    这篇文章主要介绍了基于FeignClient调用超时的处理方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07

最新评论