软件构造 | Equality in ADT and OOP

软件构造 | Equality in ADT and OOP

🧇1 Three ways to regard equality

1.1 Using AF to define the equality

ADT是对数据的抽象, 体现为一组对数据的操作

抽象函数AF:内部表示→抽象表示

基于抽象函数AF定义ADT的等价操作,如果AF映射到同样的结果,则等价

1.2 Using observation to define the equality

​ 站在外部观察者角度:对两个对象调用任何相同的操作,都会得到相同的结果,则认为这 两个对象是等价的。

在这里插入图片描述

1.3 == vs. equals()

== 引用等价性 : 对基本数据类型,使用==判定相等

equals() 对象等价性 : 对对象类型,使用equals()

在自定义ADT时,需要根据对“等价”的要求, 决定是否重写Object的equals()

1.4 Implementing equals()

The equals() method is defined by Object , and its default implementation looks like this:

在这里插入图片描述

Note:在Object中实现的默认equals()是在判断引用等价性,这通常不是程序员所期望的,因此,需要重写。

public classDuration {...// Problematic definition of equals()public boolean equals(Duration that) {return this.getLength() == that.getLength();}
}

错误声明equal:实现的是重载而不是重写。

在这里插入图片描述

正确声明

在这里插入图片描述

在 Java 中,equals() 方法是用于比较两个对象是否相等的方法。在 Java 中,所有的类都继承自 Object 类,而 Object 类中的 equals() 方法默认实现是比较两个对象的引用是否相同(即比较内存地址)。因此,当需要在自定义类中比较对象内容时,通常需要重写 equals() 方法。

下面是一个示例,展示了如何重写 equals() 方法来比较自定义类中的对象内容:

class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true; // 如果是同一个对象,直接返回true}if (obj == null || getClass() != obj.getClass()) {return false; // 如果对象为null或者是不同类的实例,直接返回false}Person person = (Person) obj; // 强制转换为Person类return age == person.age && name.equals(person.name); // 比较name和age是否相等}// 省略 getter 和 setter 方法
}public class Example {public static void main(String[] args) {Person person1 = new Person("Alice", 30);Person person2 = new Person("Alice", 30);System.out.println(person1.equals(person2)); // 输出true,因为内容相同}
}

在上面的示例中,Person 类重写了 equals() 方法,根据对象的 nameage 属性来比较两个 Person 对象是否相等。在 equals() 方法中,首先比较对象引用是否相同,然后再比较类和属性是否相同。

需要注意的是,在重写 equals() 方法时,通常需要同时重写 hashCode() 方法,以确保两个方法的一致性。这样可以保证对象在放入基于散列的集合(如 HashMapHashSet)时能够正确地根据对象内容对其进行存储和检索。

🍕 2The Object contract(对象合同)

  1. 等价关系:自反、传递、对称。
  2. 除非对象被修改了,否则调用多次equals应是同样的结果。
  3. “相等”的对象,其hashCode()的结果必须一 致。

Note:用“是否为等价关系”检验你的equals()是否正确

2.1 Hash Tables

在这里插入图片描述

Object ’s default hashCode() implementation is consistent with its default equals()

在这里插入图片描述

键值对中的 key被映射为hashcode,对应到数组的index, hashcode决定了数据被存 储到数组的哪个位置

2.2 Overriding hashCode()

在 Java 中,每个对象都有一个 hashCode,它是对象的哈希码,用于确定对象在哈希表等数据结构中的存储位置。hashCode 的作用是为了更高效地进行对象的存储和检索,特别是在使用基于散列的集合(如 HashMapHashSet)时非常重要。

hashCode 方法的设计要求是:

  1. 如果两个对象通过 equals() 方法相等,则它们的 hashCode 必须相等。
  2. 如果两个对象的 hashCode 相等,它们并不一定通过 equals() 方法相等。

在实现类中重写 hashCode 方法时,通常需要保证满足上述两个要求。通常情况下,可以利用对象的属性来生成 hashCode 值,这样可以确保同样属性的对象具有相同的 hashCode

最简单方法:让所有对象的hashCode为同一 常量,符合contract,但降低了hashTable效率

通过 equals计算中用到的所有信息的hashCode组合出新的hashCode

在 Java 中,当两个对象通过 equals() 方法相等且具有相同的 hashCode 值时,如果将这两个对象放入基于散列的集合(如 HashMapHashSet)中,只会存储一个对象。这是因为散列集合在存储对象时会先根据 hashCode 值确定对象在内部数据结构中的存储位置,然后再通过 equals() 方法来判断具体位置是否已经存在相同的对象。

具体来说,当向散列集合中添加一个对象时,首先会计算该对象的 hashCode 值,然后根据 hashCode 值找到对象在内部存储结构中的位置。如果在该位置处已经有一个对象存在,并且这个对象与新添加的对象通过 equals() 方法比较相等(即返回 true),那么新添加的对象不会被存储,以保证集合中不会存在重复的对象。

下面是一个简单示例,演示了两个相等的对象具有相同 hashCode 值时,只存储一个对象的情况:

import java.util.HashMap;
import java.util.Map;class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic int hashCode() {int result = 17;result = 31 * result + name.hashCode();result = 31 * result + age;return result;}@Overridepublic boolean equals(Object obj) {if (obj == this) {return true;}if (!(obj instanceof Person)) {return false;}Person other = (Person) obj;return this.name.equals(other.name) && this.age == other.age;}
}public class Example {public static void main(String[] args) {Map<Person, String> personMap = new HashMap<>();Person person1 = new Person("Alice", 30);Person person2 = new Person("Alice", 30);personMap.put(person1, "Value 1");personMap.put(person2, "Value 2");System.out.println(personMap.size()); // 输出 1,因为两个对象相等且具有相同的 hashCode}
}

在上面的示例中,Person 类重写了 equals()hashCode() 方法,确保在两个对象具有相同属性值时返回 true 并且具有相同的哈希码。当将这两个相等的对象放入 HashMap 中时,只会存储一个对象,因为它们具有相同的 hashCode 值。因此,最终输出的大小是 1

Always override hashCode() when you override equals()

除非你能保证你的ADT不会被放入到Hash类型的集合类中

🍿 3引用的概念

在 Java 中,引用是指向对象的指针或句柄。在 Java 中,所有对象都是通过引用来操作的,而不是直接访问对象本身。当您创建一个对象时,实际上是在堆内存中为该对象分配了空间,并返回一个引用,这个引用指向堆中的对象。Java 的引用是一种高级抽象概念,开发人员无法直接控制对象所在的内存位置,只能通过引用去访问和操作对象。

与此相对应,C 语言中的指针是直接指向内存地址的变量。在 C 中,通过指针可以直接访问或修改内存地址中的数据。指针在 C 语言中被广泛用于实现动态内存分配、访问数组元素、操作数据结构等。

下面是一个简单的示例来对比 Java 中的引用和 C 中的指针:

在 Java 中:

public class Example {public static void main(String[] args) {String str1 = "Hello";String str2 = str1;System.out.println(str1); // HelloSystem.out.println(str2); // Hellostr2 = "World";System.out.println(str1); // HelloSystem.out.println(str2); // World}
}

在这个示例中,str1str2 都是对象的引用,它们最初都指向同一个字符串对象"Hello"。当我们修改 str2 的值时,它指向了一个新的字符串对象"World",但str1 仍然指向原来的字符串对象"Hello"。

在 C 中:

#include <stdio.h>int main() {int var = 10;int* ptr = &var;printf("Original value: %d\n", var); // 10printf("Value through pointer: %d\n", *ptr); // 10*ptr = 20;printf("Updated value: %d\n", var); // 20printf("Value through pointer: %d\n", *ptr); // 20return 0;
}

在这个示例中,ptr 是一个指向 var 变量的指针。通过 *ptr 可以访问或修改 var 的值。在这段代码中,我们通过指针修改了 var 的值,而不是通过变量名 var 直接修改。

综上所述,Java 中的引用是指向对象的抽象概念,开发者无法直接操作对象的内存地址,只能通过引用访问对象;而 C 中的指针直接指向内存地址,开发者可以直接控制和操作内存地址中的数据。

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

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

相关文章

海南聚广众达电子商务咨询有限公司可信吗?

在数字化浪潮席卷全球的今天&#xff0c;电商行业已成为推动经济增长的重要力量。而在这个领域中&#xff0c;海南聚广众达电子商务咨询有限公司凭借其专业、精准的服务&#xff0c;在抖音电商领域独树一帜&#xff0c;成为行业的佼佼者。 海南聚广众达电子商务咨询有限公司自…

07-appium常用操作

一、press_keycode 1&#xff09;方法说明 press_keycode方法是appium的键盘相关函数&#xff0c;可以实现键盘的相关操作&#xff0c;比如返回、按键、音量调节等等。也可以使用keyevent方法&#xff0c;功能与press_keycode方法类似。 # KeyCode&#xff1a;各种操作对应的…

【Axure教程】移动端多选图片上传

在移动端应用中&#xff0c;提供多选图片上传功能对于用户体验和功能性具有重要意义&#xff0c;尤其是在像微信、微博等社交媒体平台上。 例如用户可以快速上传多张图片进行分享&#xff0c;发布相册或创建图文并茂的动态&#xff1b;卖家可以一次性上传多个产品图片&#xf…

劲爆!Kimi月之暗面可以接入微信,智能升级, 打造个性多Agent(二)

前言 在当今这个快速发展的AI时代&#xff0c;抖音推出了一个名为“扣子Coze”的工具&#xff0c;帮助用户快速、低门槛地搭建属于自己的AI机器人。本文将详细介绍如何使用扣子Coze配置自己的AI Agent&#xff0c;并展示其在多个平台上的应用。 如何使用多个Agent 搭建更加智…

chatgpt: linux 下用纯c 编写一按钮,当按钮按下在一新窗口显示hello world

用这个程序模板&#xff0c;就可以告别只能在黑框框的终端中编程了。 在 Linux 环境下使用纯 C 语言编写一个按钮&#xff0c;当按钮按下时&#xff0c;在一个新窗口显示 "Hello World"。我们可以使用 GTK 库来实现这个功能。GTK 是一个用于创建图形用户界面的跨平台…

大模型日报|4 篇必读的大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.ChatGLM 技术报告&#xff1a;从 GLM-130B 到 GLM-4 AII Tools GLM 技术团队介绍了 ChatGLM&#xff0c;这是一个不断发展的大语言模型系列。本报告主要关注 GLM-4 语言系列&#xff0c;包括 GLM-4、GLM-4-Air 和 …

r2frida:基于Frida的远程进程安全检测和通信工具

关于r2frida r2frida是一款能够将Radare2和Frida的功能合二为一的强大工具&#xff0c;该工具本质上是一个Radare2的自包含插件&#xff0c;可以帮助广大研究人员利用Frida的功能实现对目标进程的远程安全检测和通信管理。 Radare2项目提供了针对逆向工程分析的完整工具链&…

好用的抖音短视频矩阵系统推荐:筷子剪辑,超级编导。抖去推

目前短视频矩阵行业如火如荼&#xff0c;为大家推荐几款比较好用的短视频矩阵系统。 第一款叫做筷子剪辑&#xff0c;由筷子科技开发&#xff0c;网页版应用工具&#xff0c;无需下载安装 主打视频剪辑&#xff0c;支持一键成片&#xff0c;视频发布等&#xff0c;&#xff0…

RS-232协议详解:深入理解与实际应用

RS-232协议详解 RS-232协议&#xff0c;也称为推荐标准232&#xff0c;是一种用于串行通信的标准协议。它在计算机和外围设备之间的通信中广泛应用。本文将详细介绍RS-232协议的各个方面&#xff0c;包括其历史、工作原理、信号类型、连接方式、应用场景等。希望通过这篇文章&a…

靠这套车载测试面试题系列成功哪些20k!

HFP测试内容与测试方法 2.3 接听来电&#xff1a;测试手机来电时&#xff0c;能否从车载蓝牙设备和手机侧正常接听】拒接、通话是否正常。 1、预置条件&#xff1a;待测手机与车载车载设备处于连接状态 2、测试步骤&#xff1a; 1&#xff09;用辅助测试机拨打待测手机&…

24年计算机等级考试22个常见问题解答❗

24年9月计算机等级考试即将开始&#xff0c;整理了报名中容易遇到的22个问题&#xff0c;大家对照入座&#xff0c;避免遇到了不知道怎么办&#xff1f; 1、报名条件 2、报名入口 3、考生报名之后后悔了&#xff0c;不想考了&#xff0c;能否退费&#xff1f; 4、最多能够报多少…

计网课设-发送TCP数据包

一、效果展示 二、代码实现 import nmap import socket import tkinter as tk from tkinter import messagebox,Listbox from threading import Thread#获取自身IP&#xff0c;从而确定当前局域网范围 def get_ip_address():#创建了一个socket对象&#xff0c;socket.AF_INET表…

国际版多商户商城小程序源码(Android+IOS+H5)

一站式全球购物新体验 功能介绍 精准分类、我的团队、开通会员我的返利、我的订单、快速购买 邀请返利、购物车、我的提现 一、引言&#xff1a;为何选择国际版多商户商城小程序&#xff1f; 随着全球化的步伐不断加快&#xff0c;越来越多的人开始追求国际化的购物体验。国…

FreeBSD在zfs挂接第二块ssd 硬盘

为FreeBSD机器新增加了一块ssd硬盘&#xff1a;骑尘 256G 先格式化分区硬盘 进入bsdconfig 选Disk Management 选择ada1 &#xff0c;也就是新增加的硬盘 选择auto 然后选择Entire Disk 提示信息 The existing partition scheme on this disk (MBR) │ …

代码随想录训练营Day 64|卡码网98. 所有可达路径(深搜)

1.所有可达路径 98. 所有可达路径 | 代码随想录 代码&#xff1a; &#xff08;深搜&#xff09;邻接矩阵表示 #include <iostream> #include <vector> using namespace std; vector<int> path; vector<vector<int>> result; void dfs(const ve…

小摩法兴纷纷转多,看涨港股的时机来了吗?

恒生指数今日高开一度上涨89点报18520点&#xff0c;创近两周高。之后持续震荡下行&#xff1b;恒指临近中 午跌幅扩大&#xff0c;恒生科技指数一度跌近1.5%。截止收盘&#xff0c;恒生指数跌0.52%&#xff0c;盘面上&#xff0c;石油、煤炭、环保、建筑节能等板块涨幅居前&a…

新手下白对Latex下手啦!

第一次使用latex&#xff0c;浅浅地记录一下子吧。 首先我们一般会下载一个latex模板&#xff0c;如果想知道咋下载&#xff0c;评论去告诉俺哟&#xff01; 新手小白首先要看懂结构&#xff0c;不然完全下不了手&#xff0c;本文就以IEEE的模板&#xff0c;从头往下讲咯~ 第…

OpenAI 推出“模型规范”:塑造责任制的人工智能的框架

为了提升人工智能开发的责任性和透明度&#xff0c;OpenAI 最近发布了一份名为“模型规范”的初步草案。这份文件首次明确了其 API 和 ChatGPT 模型行为的指导原则&#xff0c;并通过博客形式对外公布。 OpenAI 在博客中解释说&#xff1a;“我们之所以发布此文档&#xff0c;…

云渲染全攻略:平台精挑细选与技巧指南

在数字化浪潮中&#xff0c;创意产业的每一步进步都得益于技术革新。云渲染技术以其卓越的效率和灵活性&#xff0c;已成为推动影视、建筑、游戏等创意行业快速发展的关键力量。本文将为您提供一份详尽的云渲染指导手册&#xff0c;涵盖平台挑选策略和操作技巧&#xff0c;助您…

Centos7.9安装kerberos

文章目录 一、背景二、Kerberos安装部署2.1kerberos服务端必要软件安装2.2配置krb5.conf2.3配置kdc.conf2.4配置kadm5.acl2.5创建Kerberos数据库2.6启动Kerberos服务2.7创建Kerberos管理员principal2.8客户端安装kerberos2.9Kerberos功能验证 本人其他相关文章链接 一、背景 亲…