首页 > 其他分享 >深入理解不可变对象

深入理解不可变对象

时间:2023-07-04 23:57:57浏览次数:46  
标签:String 对象 不可 value 理解 深入 字符串 string

前言

说到不可变对象,想必大部分人都不会陌生。Java程序员在日常开发过程中100%会用到的 String 对象就属于不可变对象吗,今天我们就来聊聊不可变对象这个话题。

什么是不可变对象

《Effective Java》中是这样定义不可变对象的:

不可变对象(Immutable Object):对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。

简单的说,就是一个对象在创建后,不能对该对象进行任何更改。比如下面这段代码:

public class ImmutableObject {
    private int value;
     
    public ImmutableObject(int value) {
        this.value = value;
    }
     
    public int getValue() {
        return this.value;
    }
}

因为 ImmutableObject 不提供任何 setter 方法,并且成员变量 value 是基本数据类型,getter 方法返回的是 value 的拷贝,所以一旦 ImmutableObject 实例被创建后,该实例的状态无法再进行更改,因此该类具备不可变性。

String类

我们常见的String类,为什么说字符串是不可变的?我的代码中经常改变String的值啊!如下所示:

String string = "ABC";
string = string.concat("DE");

这样,上面的字符串不就改变成"ABCDE"了么?但是实际上,我们得到的已经是一个新的字符串。

程序会在堆中重新创建一个"ABCDE"字符串,和"ABC"并不是同一个对象。

所以,一旦一个string对象在内存(堆)中被创建出来,他就无法被修改。而且,String类的所有方法都没有改变字符串本身的值,都是返回了一个新的对象。

string类如何设计成不可变

  1. String 类被 final 关键字修饰,所以它不会有子类,这就意味着没有子类可以重写它的方法,改变它的行为。
  2. String 类的数据存储在 char[] 数组中,而这个数组也被 final 关键字修饰了,这就表示 String 对象是没法被修改的,只要初始化一次,值就确定了。

不可变的好处

安全性

String 是 Java 中最基础也是最长使用的类,经常用于存储一些敏感信息,例如用户名、密码、网络连接等。因此,String 类的安全性对于整个应用程序至关重要。

节省空间(字符串常量池)

通过使用常量池,内容相同的字符串可以使用同一个对象,从而节省内存空间。如果 String 是可变的,试想一下,当字符串常量池中的某个字符串对象被很多地方引用时,此时修改了这个对象,则所有引用的地方都会改变,这可能会导致预期之外的情况。

性能

String 被广泛应用于 HashMap、HashSet 等哈希类中,当对这些哈希类进行操作时,例如 HashMap 的 get/put,hashCode 会被频繁调用。

线程安全

String 对象是不可修改的,如果线程尝试修改 String 对象,会创建新的 String,所以不存在并发修改同一个对象的问题。

由于不可变性,String 的 hashCode 只需要计算1次后就可以缓存起来,因此在哈希类中使用 String 对象可以提升性能。

总结

由于字符串是不可变的,因此它们的引用可以被视为普通变量,可以在方法之间和线程之间传递它们,而不必担心它所指向的实际字符串对象是否会改变。

标签:String,对象,不可,value,理解,深入,字符串,string
From: https://www.cnblogs.com/GentleJim/p/17527397.html

相关文章

  • NestJs NestFactory.create()方法的可选的配置对象
    NestJs是一个用于构建高效、可扩展和可维护的Nodejs应用程序的框架。NestFactory是nestjs框架中的一个重要类,第一个参数接受一个根模块作为参数,第二个参数是一个可选的配置对象,用于配置应用程序实例的行为和属性。这个配置对象可以包含如下属性:logger:指定自定义的日志记录器,用于......
  • 深入解读核心资源Pod
    一、Pod概念Pod是Kubernetes中最小的调度单位,是一组容器的集合,Pod中的容器共享网络和存储资源,Pod中的容器可以通过localhost进行通信,Pod中的容器可以通过共享的Volume进行数据共享。k8s是通过定义一个Pod的资源,然后再Pod里面运行容器,容器需要指定一个镜像,这样就可以用来运......
  • 关于JAVA项目公共字段自动填充的理解
    公共字段字段填充是什么? “公共字段自动填充”顾名思义,其实就是省略了在程序当中对某些字段手动填写的步骤,大大提高了效率! 为什么要使用公共字段填充技术在我们的程序当中? 在我们项目的开发中,当我们在修改数据库中的某些值的时候,有一些字段属于公共子段,就是有些字段不仅是......
  • 012双写一致性之定时更新,异步发送短信,异步秒杀逻辑前后端,课程页面前端,课程相关表分析,
    0双写一致性之定时更新#一旦加入缓存,就会出现数据不一致的请请求#双写一致性问题 -1改数据,删缓存-2改数据,改缓存-3定时更新#首页轮播图存在双写一致性问题这个问题 -以现在的技术水平(信号),做不到:改数据删缓存 -能选择的就是定时更新 -轮播......
  • 个人对面向对象和面向过程的认识
    面向过程和面向对象的区别:面向过程和面向对象都是对软件分析、设计和开发的一种思想,它指导着人们以不同的方式去分析、设计和开发软件。C语言是一种典型的面向过程语言,Java是一种典型的面向对象语言。面向过程适合简单、不需要协作的事务,重点关注如何执行。面向对象(Oriented......
  • 深入浅出时序数据库之预处理篇——批处理和流处理,用户可定制,但目前流行influxdb没有做
    时序数据是一个写多读少的场景,对时序数据库以及数据存储方面做了论述,数据查询和聚合运算同样是时序数据库必不可少的功能之一。如何支持在秒级对上亿数据的查询分组聚合运算成为了时序数据库产品必须要面对的挑战。 本文会从时序数据库的查询以及聚合运算角度展开,最后会从如何解决......
  • 时序数据库深入浅出之存储篇——本质LSMtree,同时 metric(比如温度)+tags 分片
    什么是时序数据库先来介绍什么是时序数据。时序数据是基于时间的一系列的数据。在有时间的坐标中将这些数据点连成线,往过去看可以做成多纬度报表,揭示其趋势性、规律性、异常性;往未来看可以做大数据分析,机器学习,实现预测和预警。时序数据库就是存放时序数据的数据库,并且需要支持时序......
  • NLP | 数据集独立同分布的理解
    在自然语言处理(NLP)中,独立同分布是指一个数据集中的样本是从同一个总体分布中独立采样而来的。这意味着数据集中的每个样本都具有相同的概率分布,并且这些样本之间是相互独立的,即一个样本的出现不会影响其他样本的出现。例如,如果我们收集了一组用于训练文本分类器的新闻文章,并且这......
  • Servlet p6 HttpSession对象
    HttpSession对象HttpSession对象是javax.servlet.http.HttpSession的实例,该接口井不像HttpServletRequest或HttpServletResponse还存在一个父接口,该接口只是一个纯粹的接口。这因为session本身就属于HTTP协议的范畴。对于服务器而言,每个来连接到它的客户端都是一个Session,Serv......
  • 充血模型和贫血模型的理解
     一、贫血模型1.介绍贫血模型是指领域对象里只有get和set方法(POJO),所有的业务逻辑都不包含在内而是放在BusinessLogic层。 2.优点各层单向依赖,结构清楚,易于实现和维护。设计简单易行,底层模型非常稳定。3.缺点domainobject的部分比较紧密依赖的持久化domainlogic被分......