面向对象中不可变性

news2024/11/15 10:26:59

软件设计中的不可变性是一个非常重要的概念,它可以在多个方面提高代码的可靠性、可维护性和安全性。

从开发者角度(代码提供者):

在软件开发过程中,当某个对象的属性是不可变的时候,这意味着这些属性的值在对象创建后不会改变。这种不可变性对于开发者来说有着重要的意义:

  • 代码逻辑假设的保护:当开发者在编写代码时,可以假设某个属性是不可变的,从而建立起相应的代码逻辑。如果这个假设被打破,可能会导致代码错误或者逻辑混乱。因此,对象属性的不可变性可以保护代码逻辑的正确性,减少代码维护的复杂性。

从使用者角度(代码调用者):

从使用者的角度来看,依赖于对象的某个属性是不可变的意味着使用者可以放心地使用这个属性,而不用担心它会在运行时被修改。这样可以降低使用者犯错的可能性:

  • 避免意外修改的风险:使用者不必担心对象的某个属性会在他们不知情的情况下被修改,从而避免了因为意外修改而引发的错误。这种信任关系可以帮助使用者更加自信地使用对象,并且降低了代码出错的风险。

不可变对象Immutable Objects 带来那些好处

可以引用传递,可以缓存

在 Java 中,除了基本类型(小写 byte/short/int/long/float/double/char/boolean)之外,所有其他类型都是引用传递,你也操作这个对象我也操作这个对象引用 这个对象变掉了系统就会出错
不可变性的特性之一是它们可以进行引用传递并且可以缓存。以下是关于这两个方面的总结:

  1. 可引用传递

    • 不可变对象可以被安全地引用传递给其他对象或方法,因为它们的状态不会改变。
    • 当传递不可变对象时,不需要担心对象在传递过程中被修改导致意外的行为。
  2. 缓存

    • 由于不可变对象的值在创建后不会改变,因此它们可以被安全地缓存。
    • 缓存不可变对象可以提高性能,因为它们的值在整个应用程序生命周期内都是固定的,不需要重新计算或重新获取。

线程安全

当谈到线程安全时,不可变对象(Immutable Objects)是一个非常重要的概念。不可变对象的不可变性使它们天然地具有线程安全性,这对于多线程编程非常有价值。以下是对不可变性如何加强线程安全理解的总结:

  1. 不可变对象不可变性保证

    • 不可变对象的值在创建后不可改变,这意味着它们不会出现竞态条件或数据竞争。
    • 因为不可变对象的状态不会改变,所以多个线程可以同时访问它们而不会导致线程安全问题。
  2. 无需同步措施

    • 由于不可变对象不会改变,因此不需要同步措施(如锁)来保护它们的状态。
    • 这消除了因为同步带来的性能开销和可能的死锁、饥饿等问题,简化了多线程编程。
  3. 并发性能提升

    • 不可变对象的线程安全性意味着多个线程可以同时访问它们,而无需等待或竞争锁资源。
    • 这可以提高应用程序的并发性能,尤其是在高并发环境下。
  4. 防止意外修改和副作用

    • 不可变对象的不可变性可以防止意外的状态变化和副作用。
    • 这使得代码更加可靠和易于理解,因为开发者不需要担心对象的状态在其它地方被修改。
  5. 线程安全的集合

    • 不可变集合类(如 ImmutableListImmutableMap 等)提供了线程安全的集合实现。
    • 这些集合类的不可变性确保了多线程环境下的安全访问,避免了对普通集合类进行手动同步的麻烦。
  6. 使用不可变对象的最佳实践

    • 在设计和实现中,尽量使用不可变对象来减少线程安全问题的发生。
    • 在多线程环境中,特别是在高并发场景下,使用不可变对象可以降低线程安全问题的概率,并简化代码的编写和维护。

综上所述,不可变对象的不可变性是实现线程安全的重要手段之一。通过使用不可变对象,可以提高应用程序的并发性能,减少线程安全问题的发生,并简化多线程编程的复杂性。

java中实现不可变性实践

在这里插入图片描述

final 关键字无法保证不可变性

在 Java 中,final 关键字可以用来修饰变量、方法和类,但它并不能完全保证不可变性。尽管使用 final 关键字可以确保变量引用不会改变,但如果引用的对象本身是可变的,那么对象的状态仍然可以被修改。因此,使用 final 关键字只能确保引用的不可变性,而不是对象本身的不可变性。

从接口定义、类的实现上保证不可变性

要实现真正的不可变性,需要从接口定义和类的实现两个方面来保证。首先,在接口定义中应该尽可能地限制对于对象状态的访问和修改,只提供读取数据的方法而不提供修改数据的方法。其次,在类的实现中需要确保所有的属性都是私有的,并且不提供任何修改属性的方法。通过这种方式,可以确保对象的状态在创建后不会改变,从而实现了真正的不可变性。

Collections.unmodifiableXXX 方法(确保List引用的不可变性方法)

Java 中的 Collections 类提供了一系列静态方法来创建不可变的集合对象,如 unmodifiableList()unmodifiableSet()unmodifiableMap() 等。这些方法接受一个普通的集合对象,并返回一个不可变的视图。这样一来,即使原始集合对象发生改变,返回的不可变视图也不会受到影响。

// 定义 Employee 类作为基类
public class Employee {
    private final String name;
    private final int salary;

    // 构造方法
    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    // 获取员工姓名
    public String getName() {
        return name;
    }

    // 获取员工薪水
    public int getSalary() {
        return salary;
    }
}
// 定义 Manager 类作为 Employee 的子类
public class Manager extends Employee {
    // 使用 final 关键字确保 reporters 属性不可变
    private final List<Employee> reporters;

    // 构造方法
    public Manager(String name, int salary, List<Employee> reporters) {
        // 调用父类的构造方法
        super(name, salary);
        // 创建一个新的 ArrayList 对象,并将 reporters 中的元素复制到新列表中
        List<Employee> tmpList = new ArrayList<>(reporters);
        // 使用 Collections.unmodifiableList() 方法确保不可变性
        this.reporters = Collections.unmodifiableList(tmpList);
    }

    // 获取下属列表
    public List<Employee> getReporters() {
        return reporters;
    }
}

在这里插入图片描述

在上述代码中,为了确保 reporters 属性的不可变性,使用了 new ArrayList<>(reporters) 的方式来创建一个新的 ArrayList 对象。这种做法是为了防止外部的修改影响到 reporters 属性。

具体来说,new ArrayList<>(reporters) 会创建一个新的 ArrayList 对象,并将 reporters 中的元素复制到这个新的列表中。这样一来,即使外部对原始的 reporters 列表进行了修改,新创建的 ArrayList 对象不受影响,保持了原始状态。然后,通过 Collections.unmodifiableList() 方法对这个新的列表进行包装,以确保它的不可变性。

这样做的目的是为了避免外部对 reporters 列表的直接修改,从而保护了对象的不可变性。这种做法是不可变对象的一种常见实现方式,能够确保对象在创建后不会被修改,从而提高了代码的可靠性和安全性。

例如,Collections.unmodifiableList() 方法可以将一个普通的 List 对象转换为不可变的列表,从而确保列表的内容不会被修改。

综上所述,通过合理地设计接口和类,并结合使用 Collections.unmodifiableXXX() 方法,可以在 Java 中实现不可变性,并确保对象在创建后不会被修改,从而提高程序的健壮性和可靠性。

软件设计不可变性的重要性:

综上所述,不可变性在软件设计中具有重要的地位和价值。它可以保护代码逻辑的正确性,降低代码维护的难度;同时也可以增强使用者对于对象的信任,降低使用者犯错的可能性。因此,在软件设计中,应该充分考虑并合理利用不可变性,从而提高软件系统的稳定性、安全性和可维护性。

这样的文章结构可以更好地向读者阐述不可变性的重要性和作用,并且提醒他们在软件设计和开发中要重视不可变性的应用。


扩展阅读

在这里插入图片描述

面向对象主题链接
类与对象链接
接口与抽象类链接
不可变性链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1500213.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ASP站点故障页面报503错误

本周有一个Hostease客户&#xff0c;购买Windows主机创建ASP站点&#xff0c;反馈站点遇到故障&#xff0c;页面报503错误。我们测试&#xff0c;复现了这个问题&#xff0c;随即检查独立应用池状态&#xff0c;发现它离线&#xff0c;通过重启操作站点恢复访问。我们分享这个教…

Redis与 Memcache区别

Redis与 Memcache区别 1 , Redis 和 Memcache 都是将数据存放在内存中&#xff0c;都是内存数据库。不过 Memcache 还可用于缓存 其他东西&#xff0c;例如图片、视频等等。 2 , Memcache 仅支持key-value结构的数据类型&#xff0c;Redis不仅仅支持简单的key-value类型的数据&…

ThreeJs限制模型拖动的范围

之前有讲过ThreeJs中对模型的拖动功能&#xff0c;使用DragControl组件&#xff0c;将模型放到组件的集合中&#xff0c;就可以拖动点击的模型了&#xff0c;这节细化下怎么控制拖动&#xff0c;比如之拖动z轴&#xff0c;或者限制拖动x轴的范围在某个区间&#xff1a; 首先还是…

【PLC】施耐德PLC数据采集经验总结-TSX系列

目录 1、介绍 2、 施耐德TSX系列 3、TSX通讯口引脚定义参考 1、介绍 施耐德&#xff0c;品牌就不介绍了&#xff0c;今天主要了解其PLC系列产品&#xff0c; 耐德PLC系列比较多&#xff0c;大公司&#xff0c;比较有钱&#xff0c;收购较多PLC厂家&#xff0c;导致PLC型号、编…

Vessel - Linux hackthebox

#hard #runc #RE #Nodejs-SQLI Enumeration .git leak 使用 dumpall 下载 .git 打开 routes/index.js 可以看到网站使用 nodejs mysql 编写&#xff0c;且只有登录功能 router.post(/api/login, function(req, res) {let username req.body.username;let password req…

代码随想录算法训练营第day7|454.四数相加II 、383. 赎金信 、 15. 三数之和 、18. 四数之和

目录 a.454.四数相加II b. 383. 赎金信 c. 15. 三数之和 d.18. 四数之和 a.454.四数相加II 题目链接 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l…

微信小程序开发系列(二十四)·wxml语法·列表渲染·wx:for-item 和 wx:for-index

目录 1. 如果需要对默认的变量名和下标进行修改&#xff0c;可以使用wx:for-item 和 wx:for-index 2. 将 wx:for 用在 标签上&#xff0c;以渲染一个包含多个节点的结构块 方法一 方法二 3. 总结 3.1 wx:for-item 和 wx:for-index总结 3.2 总结 1. 如果需要对默…

Publii和GitHub:搭建个人网站的完美组合

在数字时代&#xff0c;拥有一个个人网站已经非常普遍了&#xff0c;但是&#xff0c;很多人因为技术难题而望而却步。现在&#xff0c;有了Publii&#xff0c;这一切都将变得简单。Publii是一个静态网站生成器&#xff0c;它允许你在本地计算机上创建和管理内容&#xff0c;然…

​项目文章 | METTL3敲减通过m6A-YTHDC2介导的AMIGO2调控抑制RA-FLS活化

类风湿性关节炎&#xff08;RA&#xff09;是一种自身免疫性关节疾病&#xff0c;其特征是慢性关节滑膜炎、滑膜增生过度和关节损伤。近年来&#xff0c;N6-甲基腺苷&#xff08;m6A&#xff09;修饰的RNA在癌症和自身免疫疾病&#xff08;包括RA&#xff09;中的调控作用受到广…

全球科技创新领域大检阅“2024上海国际智能科技及创新展览会”

随着科技的飞速发展&#xff0c;创新成为了推动社会进步的核心动力。在这样的背景下&#xff0c;“2024上海国际科技及创新展览会”应运而生&#xff0c;旨在汇聚全球智能科技领域的精英&#xff0c;共同展示最新的科技成果&#xff0c;探讨未来的发展方向。 本次展会将于2024年…

在人工智能领域,如何平衡技术进步和人类安全?

人工智能&#xff08;AI&#xff09;技术的迅速发展为人类社会带来了许多潜在益处&#xff0c;但同时也引发了一系列安全和伦理挑战。在这个领域&#xff0c;如何平衡技术进步与人类安全成为了至关重要的议题。本文将探讨在人工智能领域中平衡技术进步与人类安全的方法&#xf…

Java安全 CC链3分析

Java安全 CC链3分析 cc链3介绍前置知识类加载类加载的方法例1.forName例2.getSystemClassLoader总结 javassist模块 cc链3分析TemplatesImpl类demo2TrAXFilter类InstantiateTransformer类 最终exp基于LazyMap链基于TransformedMap链 cc链3介绍 cc链3的后半部分与cc链1相同&…

阿里云服务器怎么使用?3分钟搭建网站教程2024新版

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网aliyunfuwuqi.com以搭建WordPress网站博客为例&#xff0c;来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流…

【梳理】k8s使用Operator搭建Flink集群

文章目录 架构图安装cert-manager依赖helm 安装operator运行集群实例k8s上的两种模式&#xff1a;Native和Standalone两种CRDemo1&#xff1a;Application 单任务Demo2&#xff1a;Session 多任务创建ingress 总结 架构图 参考&#xff1a;部署验证demo 安装cert-manager依赖 …

C# LINQ基础

LINQ基础 1. 入门2. 运算符流语法2.1 连续使用查询运算符2.2 使用Lambda表达式2.2.1 Lambda表达式及Func的方法签名2.2.2 Lambda表达式和元素类型2.2.3 自然排序2.2.4 其他查询运算符 3 查询表达式4 延迟执行4.1 重复执行4.2 捕获的变量4.3 延迟加载的工作原理4.4 查询语句的执…

ARM-v7 GCC 环境下的大小端转换实现

1.前言 什么是大小端转换&#xff1f;为什么叫大小端转换&#xff1f; Jonathan Swift的《格列佛游记》中记载&#xff0c;有两国因为剥鸡蛋的方式不同&#xff0c;即一国要求将熟鸡蛋的较大的一端&#xff08;大端&#xff0c;big endian&#xff09;敲碎然后剥壳&#xff0c;…

NLP_文本数据分析_3(代码示例)

目标 了解文本数据分析的作用.掌握常用的几种文本数据分析方法. 一、 文件数据分析介绍 文本数据分析的作用: 文本数据分析能够有效帮助我们理解数据语料, 快速检查出语料可能存在的问题, 并指导之后模型训练过程中一些超参数的选择. 常用的几种文本数据分析方法: 标签数量分…

【嵌入式——QT】Model/View

【嵌入式——QT】Model/View 基本原理数据模型视图组件代理Model/View结构的一些概念QFileSystemModelQStringListModelQStandardItemModel自定义代理 基本原理 GUI应用程序的一个很重要的功能是由用户在界面上编辑和修改数据&#xff0c;典型的如数据库应用程序&#xff0c;数…

leetcode刷题(javaScript)——字典哈希表相关场景题总结

在 JavaScript 刷题中&#xff0c;字典&#xff08;Dictionary&#xff09;和哈希表&#xff08;Hash Table&#xff09;通常用来存储键值对&#xff0c;提供快速的查找、插入和删除操作。它们在很多算法题目中都有广泛的应用&#xff0c;特别是在需要快速查找元素或统计元素出…

Unity插件之天气系统UniStorm

首先呢&#xff0c;它是一款强大的动态昼夜天气系统&#xff0c;能够以较快的帧速率创建AAA级动态生成的天气、照明和天空&#xff0c;并且具有300多个可定制的组件&#xff0c;允许用户创建任何可以想象的环境。 第一步&#xff1a;他需要两个物体Camera摄像机、Player播放器…