java:示例中不可变对象的优点

如何解决java:示例中不可变对象的优点

|                                                                                                                       

解决方法

不变性在多线程程序中很重要,因为这样您就知道一个线程不会破坏另一个线程中使用的值。但它在单线程程序中也很有用。 这是一个简单的示例:
Integer i=Integer.valueOf(17);
foo(i);
bar(i);
您可能想知道,什么值传递给bar()? 假设foo()是一个大型复杂函数。在此示例中,我绝对知道foo完成时,我仍然等于17,因为Integer是不可变的。如果不是真的,我将必须研究foo才能确定它是否可能被更改。 这是一个稍微复杂的例子。假设我有一些类似于Integer但可变的对象。让我们将其称为MutableInteger。然后说我写这个:
MutableInteger currentInventory=findQtyInInventory();
MutableInteger neededInventory=currentInventory; // copy current for starters
... bunch of other code ...
neededInventory.subtract(allocatedToSales);
currentInventory.add(arriving);
... bunch of more code ...
if (neededInvenory.compareTo(currentInventory)>0)
  display(\"Shortage!\");
您是否看到上述问题? neededInventory和currentInventory指向同一对象。所有的加法和减法实际上都作用于相同的值,而不是两个不同的值,因此,当我们进行测试时,它将始终相等。如果对象是可变的,则上面的代码将永远无法工作。如果它们是不可变的,则加法和减法将必须返回结果对象,而不是就地更新,这将起作用。 多年前,我使用了Fortran编译器,其中整数是可变的。我们有一个接受几个参数的函数,其中一个是整数。在极少数情况下,函数会更新整数。然后有一天,有人对此函数进行了调用,将常量“ 2”作为整数传递。该函数决定更新参数,从而将“常量” 2更改为1!程序中使用常数2的每个其他位置现在都神秘地取值为1。这花费了很长时间进行调试。     ,这不是一个可以通过示例进行有用解释的概念。不变对象的优点是您知道它们的数据无法更改,因此您不必为此担心。您可以自由地传递它们,而不必记住传递给它们的方法是否可能以您的代码不准备处理的方式更改它们。这使得处理不可变数据变得更加容易。 对于多线程而言,这一优势更为重要,因为基于多线程以不应该更改的方式更改数据的错误通常是不可重现的-它们依赖于时序,因此有时会发生,有时甚至不会,这使得它们非常难以分析和修复。     ,当Java按值返回时(即对象引用是从方法返回的),例如,如果我返回一个String像这样:
private String myString = \"foo\";

public String getString() {
    return this.myString;
}
并且String类不是不可变的,则
getString()
的调用者可以修改
myString
,这可能不是所需的行为;系统的其他部分可能不希望或期望ѭ4更改。因此,调用者只能更改
myString
指向的对象,而不能更改
myString
本身。     ,这是重言式的,但是不可变对象的主要优点是它们不能更改。当对象可以更改时,您必须考虑它们可能会发生什么。您必须考虑如何,何时以及为何要更改它们。您必须考虑应用程序中还有哪些其他代码可以访问同一对象,以及在不知情的情况下可能会更改什么。不可变的对象有效地减少了您必须在系统中使用的“活动部件”的数量(和粒度),并使您的生活更轻松。     ,如您所知,这是多线程的绝佳模式。 这也意味着更好的封装。您可以传递这些对象并共享它们,而您永远不必担心有人会更改您对象的状态。 Java核心库中有一些很棒的例子。数字子类是一个,但我认为最好的例子是
String
。您可以将它们传递,连接,获取子字符串等,而无需考虑其他地方。如果它像C / C ++
char[]
一样易变,则始终需要牢记这一点。 出于相同的原因,它还导致了更具可读性和可维护性的代码。无需关心对象的其他用户。 这两个原因导致我们进入另一个重要的模式,称为值对象。简而言之,当您关心某个特定值(日期,数字,字符串,间隔,金钱或一些稍微复杂的对象(如果需要))时,这很有意义,但是值本身没有身份,即它具有无论上下文如何,其含义完全相同。     ,当对象通常被共享时,不可变对象非常有用-不仅与线程共享,而且在单线程程序中,对象也具有许多客户端。 例如,
String
可能是Java中使用最多的不可变对象。阻止该字符串的用户更改其内容是不变的。如果“ 8”是可变的,则意味着每个用户都必须创建该字符串的唯一副本,以确保没有其他人对其进行更改。 不变的数据也具有安全隐患。例如,与用户关联的安全令牌应该是不可变的,否则流氓程序可能会轻易更改与该令牌关联的用户。     ,这里的主要思想是通过使用不可变对象使您的类线程安全。我认为这篇文章对此很不错。 希望这可以帮助!     ,
String
类就是一个很好的例子: 关于不可变对象的原因的很好总结可以在这里找到     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res