Java中如何创建不可变(immutable)类

  1. 不可变类是指类的实例一经创建完成,这个实例的内容就不会改变。

  2. Java中的String和八个基本类型的包装类(Integer, Short, Byte, Long, Double, Float,Boolean,Char)都是不可变类

3.不可变类 vs 不可变变量:

二者是不一样的。

不可变类是指类的实例内容不会改变,考虑如下代码:

在line 2中我们对s变量进行了再次赋值,实际上是又创建了一个值为”BCD”的String 对象,并将s指向它。变化的是s指向的内存地址(或者简单的叫指针),值为”ABC” 与值为”BCD”的两个String 对象是没有变的

不可变变量是用Final关键字修饰的变量,考虑如下代码:

我们将s变量用final关键字修饰,这时在s被初始化之后,就无法在line 2 再次给它赋值了,也就是说 我们没办法改变final变量指向的内存地址

  1. 所有的成员变量声明为private final,防止初始化后被修改

  2. 类声明为final,禁止继承,其实是防止类中的方法被重写

  3. 不为成员变量提供setter方法

  4. 如果类中包含可变对象,比如一个成员变量是数组,或者其他可变类,那么要有如下操作:

1)在构造方法中,如果构造方法会传入可变对象,我们要使用这个对象的copy来初始化我们的成员变量,而不是直接使用传入的对象。因为传入的是指针,传入的对象在外面可能会被修改,如果直接引用的话会导致我们的成员变量也间接被修改。

2) 在返回这些可变对象的getter方法中,返回对象的copy,而不是直接返回该对象(或者叫该对象的引用/指针)

实例:

下面探讨一下为何类也需要声明为final. 考虑如下代码:

我们把上面Immutable 类的final 声明去掉,ImmutableChild继承了Immutable类,重写了getVArr方法,返回自己的成员变量数组vArr,而这个子类里面的vArr是可变的,在main方法里面初始化时我们给其赋值{3,4},可以看到后面我们改成了{33,44}.

在使用中,任何一个接受Immutable实例的地方都可以接受其子类ImmutableChild实例,并将它作为一个不可变的实例来操作,而实际上它是可变的,这样就有可能出错。

所以把不可变类声明为final是为了防止恶意继承,或者继承中考虑不周密导致的问题。

  1. 线程安全,省去了加锁的过程,因为对象内容不可变就不用担心线程同时对对象做修改

  2. 拷贝效率高。当类不可变时, 拷贝其对象只需拷贝指针即可,而不用拷贝对象本身,不用担心会被修改

  3. 可以作为HashMap的key,类不可变保证了Hashcode的稳定性。

当然,也要注意不可变类在使用过程中可能出现的内存浪费问题,比如大家都知道的最好不要用许多”+”连接String

Original: https://www.cnblogs.com/adeline-tech/p/16655521.html
Author: adeline.pan
Title: Java中如何创建不可变(immutable)类

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/604486/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 二分查找(Java实现)

    有没有正在学数据结构的?没学过C,只会Java的我表示算法好难 ┭┮﹏┭┮。 废话不多说,分享一个很简单的二分查找,在有序数组(从小到大排序)中查找T类型的变量,我就直接用int …

    数据结构和算法 2023年6月7日
    0120
  • 1.层次遍历

    📃 题目描述 题目链接:二叉树的层次遍历 🔔 解题思路 简简单单,用队列来保存每一层的数量,再进行遍历。 class Solution { public: vector> l…

    数据结构和算法 2023年6月12日
    0116
  • elasticsearch为什么比mysql快

    mysql关系型数据库索引原理 数据库的索引是B+tree结构 主键是聚合索引 其他索引是非聚合索引,先从非聚合索引找,见下图 elasticsearch倒排索引原理 两者对比 对…

    数据结构和算法 2023年6月7日
    088
  • Codeforces1573B

    问题描述 给你两个数组,a数组里面是1 – 2n中的奇数任意顺序排列组成,b数组里面是1 – 2n中的奇数任意顺序排列组成。 问你最少需要多少次操作能让a的…

    数据结构和算法 2023年6月7日
    0113
  • Springboot笔记

    SpringBoot HelloWorld 1.创建Meven工程 2.引入依赖 pom.xml org.springframework.boot spring-boot-star…

    数据结构和算法 2023年6月7日
    091
  • 生成报表时计算报表的截止上报时间

    每张报表有个截止上报时间,截止时间的计算稍微复杂,下面记录一下自己的写作成果。当月月报截止时间下月xx号,当季季报截止时间下季第一个月。。。 数据结构 /** * 计算报表上报截止…

    数据结构和算法 2023年6月8日
    098
  • AVL树

    平衡二叉树 平衡因子: 某个结点的左子树的高度减去右子树的高度得到的差值。 插入或删除节点后,可能会造成 AVL 树的平衡被破坏,因此,需要沿着从被插入/删除的节点到根的路径对树进…

    数据结构和算法 2023年6月8日
    090
  • linux多进程—使用mmap映射实现文件拷贝

    一、mmap共享映射区 1、创建映射区函数mmap void mmap(void addr,size_t length,int prot,int flags,int fd,off_…

    数据结构和算法 2023年6月8日
    092
  • 力扣算法JS LC [78. 子集] LC [90. 子集 II]

    给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums …

    数据结构和算法 2023年6月12日
    0123
  • 【重要】LeetCode 672. 灯泡开关 Ⅱ

    题目链接 672. 灯泡开关 Ⅱ 思路 根据题意,我们先找到每个开关影响的灯 如图所示,两个虚框的灯的状态完全一致,因此我们任意取一盏灯i,则i的状态和i + 6的状态完全一致,所…

    数据结构和算法 2023年6月8日
    0102
  • 侯捷C++内存管理学习

    Embedded Pointer 用union或struct STL — allocator malloc底层 Loki allocator “懒惰为人类进…

    数据结构和算法 2023年6月8日
    0101
  • 【题解】HDU5371 Hotaru’s proble

    Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is play…

    数据结构和算法 2023年6月12日
    086
  • CF1468H K and Medians 题解

    每次删数都会删恰好 (k-1) 个,所以删的数总个数必须是 (k-1) 的倍数。考虑最终状态,如果所有数左边不足 (\frac{k-1}{2}) 个删掉的数或右边不足 (\frac…

    数据结构和算法 2023年6月12日
    088
  • G. Even-Odd XOR(构造 位运算) CF 1722G

    题目: ​ 构造一个长度为n的序列,使奇数位上的所有数异或和 等于 偶数位上的所有数异或和 分析: ​ 由于奇数位异或和=偶数位异或和,所以可以得到奇数位异或和xor偶数位异或和=…

    数据结构和算法 2023年6月12日
    087
  • 编程四大件

    现在这个互联网时代,很多人都想往这方面发展,然后就开始疯狂学习什么 C/C++、python、Java等语言,学了一大堆语言,可到了实际项目还是什么都不会。本人也是经历过后才发现,…

    数据结构和算法 2023年6月12日
    092
  • 2006NOIP普及组:明明的随机数

    明明的随机数 时间限制:1000ms 内存限制:65536KB 题目描述: 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随…

    数据结构和算法 2023年6月8日
    0107
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球