java创建一个不可变对象

Today we will learn about the immutable class in Java. What are immutable classes? The benefits and importance of deep copy for immutability.

今天,我们将学习Java中的不可变类。 什么是不可变类? 深复制对于不变性的好处和重要性。

什么是Java中的不可变类? (What is an immutable class in Java?)

Immutable objects are instances whose state doesn’t change after it has been initialized. For example, String is an immutable class and once instantiated its value never changes.

不可变对象是实例,其状态在初始化后不会改变。 例如, String是一个不可变的类,一旦实例化,其值就永远不会改变。

Read: Why String in immutable in Java

阅读 : 为什么Java中的String不可变

Java中不可变类的好处 (Benefits of Immutable Class in Java)

An immutable class is good for caching purposes because you don’t have to worry about the value changes.

不可变的类非常适合缓存,因为您不必担心值的更改。

Another benefit of immutable class is that it is inherently thread-safe, so you don’t have to worry about thread safety in case of multi-threaded environment.

不可变类的另一个好处是,它本质上是线程安全的 ,因此在多线程环境中,您不必担心线程安全。

Read: Java Thread Tutorial and Java Multi-Threading Interview Questions.

阅读 : Java线程教程和Java多线程面试问题 。

Here I am providing a way to create an immutable class via an example for better understanding.

在这里,我通过示例提供了一种创建不可变类的方法,以更好地理解。

如何用Java创建一个不可变的类? (How to Create an immutable class in Java?)

To create an immutable class in Java, you have to do the following steps.

要使用Java创建不可变的类,您必须执行以下步骤。

  1. Declare the class as final so it can’t be extended.将课程声明为最终课程,因此无法扩展。
  2. Make all fields private so that direct access is not allowed.将所有字段设为私有,以便不允许直接访问。
  3. Don’t provide setter methods for variables.不要为变量提供setter方法。
  4. Make all mutable fields final so that its value can be assigned only once.将所有可变字段定为最终值,使其值只能分配一次。
  5. Initialize all the fields via a constructor performing deep copy.通过执行深度复制的构造函数初始化所有字段。
  6. Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.在getter方法中执行对象的克隆以返回副本,而不是返回实际的对象引用。

To understand points 4 and 5, let’s run the sample Final class that works well and values don’t get altered after instantiation.

为了理解第4点和第5点,让我们运行示例Final类,该类运行良好,并且实例化后值不会改变。

FinalClassExample.java

FinalClassExample.java

package com.journaldev.java;import java.util.HashMap;
import java.util.Iterator;public final class FinalClassExample {private final int id;private final String name;private final HashMap<String,String> testMap;public int getId() {return id;}public String getName() {return name;}/*** Accessor function for mutable objects*/public HashMap<String, String> getTestMap() {//return testMap;return (HashMap<String, String>) testMap.clone();}/*** Constructor performing Deep Copy* @param i* @param n* @param hm*/public FinalClassExample(int i, String n, HashMap<String,String> hm){System.out.println("Performing Deep Copy for Object initialization");this.id=i;this.name=n;HashMap<String,String> tempMap=new HashMap<String,String>();String key;Iterator<String> it = hm.keySet().iterator();while(it.hasNext()){key=it.next();tempMap.put(key, hm.get(key));}this.testMap=tempMap;}/*** Constructor performing Shallow Copy* @param i* @param n* @param hm*//**public FinalClassExample(int i, String n, HashMap<String,String> hm){System.out.println("Performing Shallow Copy for Object initialization");this.id=i;this.name=n;this.testMap=hm;}*//*** To test the consequences of Shallow Copy and how to avoid it with Deep Copy for creating immutable classes* @param args*/public static void main(String[] args) {HashMap<String, String> h1 = new HashMap<String,String>();h1.put("1", "first");h1.put("2", "second");String s = "original";int i=10;FinalClassExample ce = new FinalClassExample(i,s,h1);//Lets see whether its copy by field or referenceSystem.out.println(s==ce.getName());System.out.println(h1 == ce.getTestMap());//print the ce valuesSystem.out.println("ce id:"+ce.getId());System.out.println("ce name:"+ce.getName());System.out.println("ce testMap:"+ce.getTestMap());//change the local variable valuesi=20;s="modified";h1.put("3", "third");//print the values againSystem.out.println("ce id after local variable change:"+ce.getId());System.out.println("ce name after local variable change:"+ce.getName());System.out.println("ce testMap after local variable change:"+ce.getTestMap());HashMap<String, String> hmTest = ce.getTestMap();hmTest.put("4", "new");System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap());}}

Output of the above example program is:

上面的示例程序的输出是:

Performing Deep Copy for Object initialization
true
false
ce id:10
ce name:original
ce testMap:{2=second, 1=first}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{2=second, 1=first}
ce testMap after changing variable from accessor methods:{2=second, 1=first}

为什么Deep Copy对于不变性很重要? (Why Deep Copy is important for immutability?)

Let’s comment the constructor providing deep copy and uncomment the constructor providing a shallow copy.

让我们评论提供深拷贝的构造函数,并取消注释提供浅拷贝的构造函数。

Also, uncomment the return statement in the getTestMap() method that returns the actual object reference.

另外,在返回实际对象引用的getTestMap()方法中取消注释return语句。

Run the program after all the changes are done. It will produce the following output.

完成所有更改后,运行程序。 它将产生以下输出。

Performing Shallow Copy for Object initialization
true
true
ce id:10
ce name:original
ce testMap:{2=second, 1=first}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{3=third, 2=second, 1=first}
ce testMap after changing variable from accessor methods:{3=third, 2=second, 1=first, 4=new}

As you can see from the output, HashMap values got changed because of shallow copy in the constructor.

从输出中可以看到,由于构造函数中的浅表复制, HashMap的值已更改。

It’s happening because of the direct reference to the original object in the getter function.

之所以发生这种情况,是因为直接在getter函数中引用了原始对象。

That’s all for an immutable class in Java. We also learned the importance of deep copy for immutable classes.

这就是Java中不可变类的全部内容。 我们还了解了深度复制对于不可变类的重要性。

Further Reading: If the immutable class has a lot of attributes and some of them are optional, we can use builder pattern to create immutable classes.

进一步阅读 :如果不可变类具有很多属性,并且其中一些是可选属性,则可以使用构建器模式来创建不可变类 。

GitHub Repository.GitHub Repository中查看更多Java示例。

翻译自: https://www.journaldev.com/129/how-to-create-immutable-class-in-java

java创建一个不可变对象

java创建一个不可变对象_如何在Java中创建不可变类?相关推荐

  1. figma下载_如何在Figma中创建逼真的3D对象

    figma下载 by Gbolahan Taoheed Fawale 通过Gbolahan Taoheed Fawale 如何在Figma中创建逼真的3D对象 (How to create reali ...

  2. python计算均方根误差_如何在Python中创建线性回归机器学习模型?「入门篇」

    线性回归和逻辑回归是当今很受欢迎的两种机器学习模型. 本文将教你如何使用 scikit-learn 库在Python中创建.训练和测试你的第一个线性.逻辑回归机器学习模型,本文适合大部分的新人小白. ...

  3. hive 元数据 自定义_如何在Hive中创建自定义函数UDF及如何直接通过Impala的同步元数据重用UDF的jar文件-阿里云开发者社区...

    如何在Hive中创建自定义函数UDF及使用 如何在Impala中使用Hive的自定义函数 UDF函数开发 使用Intellij工具开发Hive的UDF函数,进行编译: 1.使用Intellij工具通过 ...

  4. html树状图右侧_如何在 Tableau 中创建控制图?

    本文作者:Jose Valero 控制图是用于研究流程如何随时间变化,并确定制造或业务流程是否在统计控制状态下的图表. 我相信这对每家公司来说都是一个有益的工具,所以在这篇文章中,我将尝试如何在 Ta ...

  5. vue 递归创建菜单_如何在Vue中创建类似中等的突出显示菜单

    vue 递归创建菜单 by Taha Shashtari 由Taha Shashtari 如何在Vue中创建类似中等的突出显示菜单 (How to Create a Medium-Like Highl ...

  6. 如何在mysql中创建过程_如何在MySQL 中创建存储过程?

    问题阐述 自MySQL 5.0 开始,MySQL 就支持存储过程.存储过程是一些被用户定义的SQL 语句集合.一个存储程序是可以被存储在服务器中的一套SQL 语句.存储过程可以被程序.触发器或另一个存 ...

  7. wordpress 数据库_如何在WordPress中创建视频库(逐步)

    wordpress 数据库 Recently, a user asked us how to create a video gallery in WordPress. WordPress makes ...

  8. wordpress创建_如何在WordPress中创建问卷(简易方式)

    wordpress创建 Do you want to create a questionnaire in WordPress to survey your visitors or collect da ...

  9. wordpress创建_如何在WordPress中创建子页面

    wordpress创建 Do you want to create a child page on your site? Pages in WordPress can be standalone or ...

最新文章

  1. 转载_最值得阅读学习的10个C语言开源项目代码
  2. 0046算法笔记——【随机化算法】舍伍德随机化思想解决跳跃表问题
  3. win7安装laravel
  4. 包含数字和指定字符的正则表达式_Excel公式练习39: 求字符串中的数字组成的数能够被指定数整除的数的个数...
  5. 九、N-gram语言模型
  6. 【2012百度之星/初赛下】C:度度熊的礼物
  7. hibernate中SessionFactory,Session的理解?
  8. java类型转换答案,在java中支持两种类型的类型转换,自动类型转换和强制类型转换。父类转化为子类需要强制转换。...
  9. wget命令下载文件
  10. LeetCode 166. 分数到小数
  11. 基于C语言EOF与getchar()的使用详解
  12. sql 查询数据库索引重建_SQL查询性能的杀手– –了解不良的数据库索引
  13. 电脑死机是什么原因及解决方法
  14. 如何通过组策略来缓解打印机后台处理程序漏洞CVE-2021-34527?
  15. 以太坊智能合约项目开发——Web3.py库安装及错误解决方案
  16. java POI 实现合并单元格
  17. The Shawshank Redemption-4
  18. wiredtiger java_mongodb数据库损坏,丢失WiredTIger.wt等meta文件,通过collection*.wt恢复数据...
  19. 国内五款好用的开源建站系统
  20. 卸载 UniAccessAgent 软件

热门文章

  1. 如何使用JavaScript阻止关闭窗口
  2. [转载] python string 字符串转换为字典 dict
  3. [转载] python:numpy数学函数和逻辑函数
  4. [转载] python-pandas创建Series数据类型
  5. MATLAB库函数radarvcd介绍
  6. Codeforces.612E.Square Root of Permutation(构造)
  7. 《高效能人士的7个习惯》读后摘记
  8. myeclipse堆栈溢出
  9. java使用xsd校验xml样例
  10. sqlserver 中怎样查看一个数据库中表的关系