首页 > 编程语言 >什么是 Java 中的不可变类?

什么是 Java 中的不可变类?

时间:2024-08-08 12:54:40浏览次数:17  
标签:Java String oldChar 不可 value char 变类 final

不可变类是指创建后无法修改对象状态的类。String 类是Java中典型的不可变类。

1. 不可变类的特点

  • 一旦创建,对象的状态就不能被改变。
  • 所有成员变量都是 final 类型。
  • 所有可变成员变量都是私有的,并且没有提供修改它们的公共方法。

2. 不可变类的示例

String 类为例,执行 s += "a"; 实际上是创建了一个新的 String 对象,而原始对象保持不变。

因为无法被修改,所以像执行s += "a";这样的方法,其实返回的是一个新建的String对象,老的s指向的对象不会发生变化,只是s的引用指向了新的对象而已。

3. 不可变类的优点

  • 安全性:由于对象状态不可变,可以在多线程环境中安全使用而无需同步。
  • 简单性:简化了编程模型,因为不需要考虑对象状态的变化。

4. 性能考虑

  • 在字符串拼接频繁的场景下,应避免使用 + 操作符,因为这会导致频繁创建新对象。
  • 可以使用 StringBuilderStringBuffer 来优化性能。

5. 如何实现一个不可变类?

  • 使用 final 修饰类:防止继承。
  • 使用 final 修饰所有成员变量:确保引用不可变。
  • 使成员变量私有:隐藏类的内部状态。
  • 不提供修改成员变量的公共方法:防止外部修改。

示例代码

public final class ImmutableClass {
    // String 本质是一个char 数组,然后用 final修饰,不过 final限制不了数组内部的数据,所以这还不够。
    //所以value 是用private修饰的,并且没有暴露出set方法,这样外部其实就接触不到value所以无法修改。
    private final int value;

    public ImmutableClass(int value) {
        this.value = value;
    }

    // 不提供任何修改value的方法
    
    //当然还是有修改的需求,比如replace方法,所以这时候就需要返回一个新对象来作为结果。
     public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* 避免使用 getfield 指令 */
            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) { // 如果找到了 oldChar
                char[] buf = new char[len];
                for (int x = 0; x < i; x++) {
                    buf[x] = val[x];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, share: true); // share 参数在实际代码中不存在,这里假设为简化说明
            } else {
                return this; // 如果没有找到 oldChar,返回原字符串
            }
        } else {
            return this; // 如果 oldChar 和 newChar 相同,直接返回原字符串
        }
    }
}

总结一下就是私有化变量,然后不要暴露set方法,即使有修改的需求也是返回一个新对象。

标签:Java,String,oldChar,不可,value,char,变类,final
From: https://blog.csdn.net/Alfred_tfk/article/details/141023873

相关文章

  • Flink开发:Java vs. Scala - 代码对比分析,选择你的最佳拍档
    一、引言1.1Flink简介ApacheFlink是一个开源的流处理框架,它支持高吞吐量、低延迟以及复杂的事件处理。Flink的核心是一个流式数据流执行引擎,它的针对数据流的分布式计算提供了数据分发、通信、容错机制。Flink提供了多种API,包括DataStreamAPI(用于构建流处理程序)、D......
  • 基于JAVA的宠物店会员管理系统设计与实现,源码、部署+讲解
    摘要随着计算机和网络的不断革新,世界也已进入了前所未有的电子时代。作为实用性强、应用范围广泛的会员管理系统也在被越来越多的行业所使用。当今社会经济发展迅速,宠物在人们生活中的地位也越来越高。市场上迫切需求一款便携操作的宠物会员管理。因此需要设计开发在效率、功......
  • Java 基础
    Java基础目录Java基础1第一个Java程序2IDEA中的代码结构3Variables与Types3.1数据类型3.2变量的注意事项3.3关键字3.4标识符4运算符4.1算术运算符4.1.1不同数字类型相加4.1.2字符相加4.1.3字符串相加4.3赋值运算符4.4关系运算符4.5逻辑运算符5逻辑控制语句5......
  • Java poi3.17 如何区分获取日期类型的单元格的值
     1、网上看了好多方案,似乎都没有效果。2、解决方法:如果是日期类型的单元格,index是等于3的。但是我偶尔到的情况,不是等于日期类型,也会等于3,这时获取Datedate=cell.getDateCellValue();值会报错,解决方法,就是用try/catch包起来,继续使用dataForMatter.formatCellValue(cel......
  • Java基础(面向对象)
    标签(空格分隔):Java面向对象的特征一:封装与隐藏一、问题引入当我们创建一个类的对象以后,我们可以通过“对象.属性”的方法,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和储存范围的制约。除此之外,没有其他约束条件。但是,实际问题中,我们往往需要给属性赋值加入额外......
  • [Java SE] 核心源码精讲:java.util.Optional(JDK1.8-)
    1概述:java.util.Optional该类是Java8中引入的一个用于处理可能为null的值的容器类。这是一个容器对象,可能包含或不包含非空值。自Java1.8起支持如果有值存在,isPresent()方法将返回true;而get()方法将返回该值,若无值存在,将报异常java.util.NoSuchElement......
  • Java中一维数组的学习
    一维数组目录一维数组创建数组null数组的遍历for循环遍历数组for-each循环遍历while循环遍历do-while循环遍历数组的反向遍历创建数组Java语言使用new操作符来创建数组,语法如下:arrayRefVar=newdataType[arraySize];上面的语法语句做了两件事:使用dataType[arraySize]......
  • java集成onlyoffice实现文档在线预览编辑
    一、onlyoffice是什么ONLYOFFICE是一款由AscensioSystemSIA公司开发的在线办公软件套件,它提供了文档编辑、电子表格、演示文稿和表单等多种办公工具,旨在提高团队协作效率和文档处理的便捷性。以下是关于ONLYOFFICE的详细介绍:1、软件概述名称:ONLYOFFICE文档(英文名ONLYOFFIC......
  • 如何把Connection 封装到工具类里面 调用工具类方法实现 增删改查操作 java JDBC
    如何把Connection封装到工具类里面调用工具类方法实现增删改查操作javaJDBC使用数据库连接池以HikariCP为例在JDBC中,使用数据库连接池是一个常见的做法,以提高数据库操作的效率和性能。连接池管理着一组数据库连接,这些连接可以被重用而不是每次需要时都创建新的连接。......
  • 如何把Connection 封装到工具类里面 调用工具类方法实现 增删改查操作 java JDBC使用
    如何把Connection封装到工具类里面调用工具类方法实现增删改查操作javaJDBC使用C3P0数据库连接池答:当使用C3P0作为数据库连接池时,你可以按照类似的模式来配置和使用它。以下是一个示例,展示了如何在Java项目中配置C3P0连接池,并创建一个工具类来管理数据库连接和执行基本的......