当前位置: 首页 > 编程日记 > 正文

Java基础学习总结(1)——equals方法

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

一、equals方法介绍

1.1.通过下面的例子掌握equals的用法

复制代码
 1 package cn.galc.test;
 2 
 3 public class TestEquals {
 4     public static void main(String[] args) {
 5         /**
 6          * 这里使用构造方法Cat()在堆内存里面new出了两只猫,
 7          * 这两只猫的color,weight,height都是一样的,
 8          * 但c1和c2却永远不会相等,这是因为c1和c2分别为堆内存里面两只猫的引用对象,
 9          * 里面装着可以找到这两只猫的地址,但由于两只猫在堆内存里面存储在两个不同的空间里面,
10          * 所以c1和c2分别装着不同的地址,因此c1和c2永远不会相等。
11          */
12         Cat c1 = new Cat(1, 1, 1);
13         Cat c2 = new Cat(1, 1, 1);
14         System.out.println("c1==c2的结果是:"+(c1==c2));//false
15         System.out.println("c1.equals(c2)的结果是:"+c1.equals(c2));//false
16     }
17 }
18 
19 class Cat {
20     int color, weight, height;
21 
22     public Cat(int color, int weight, int height) {
23         this.color = color;
24         this.weight = weight;
25         this.height = height;
26     }
27 }
复制代码

1.2.画出内存分析图分析c1c2比较的结果

程序:

Cat c1 = new Cat(1,1,1);

Cat c2 = new Cat(1,1,1);

执行完之后内存之中的布局如下图所示,

c1指向一个对象,c2也指向一个对象,c1c2里面装着的是这两只Cat对象在堆内存里面存储的地址,由于这两只Cat对象分别位于不同的存储空间,因此c1c2里面装着的地址肯定不相等,因此c1c2这两个引用对象也肯定不相等。因此执行:“System.out.println(c1==c2);”打印出来的结果肯定是false。因此你new出来了两个对象,你放心,这两个对象的引用永远不一样,一样的话就会把其中一个给覆盖掉了,这个可不成。c1是不是等于c2比较的是c1c2这两个引用里面装着的内容,因为new出来的两个对象的它们的引用永远不一样,因此c1c2这两个引用的内容也永远不一样,因此c1永远不可能等于c2。因此通过比较两个对象的引用是永远无法使得两个对象相等的,一模一样的。

要想判断两个对象是否相等,不能通过比较两个对象的引用是否相等,这是永远都得不到相等的结果的,因为两个对象的引用永远不会相等,所以正确的比较方法是直接比较这两个对象,比较这两个对象的实质是不是一样的,即这两个对象里面的内容是不是相同的,通过比较这两个对象的属性值是否相同而决定这两个对象是否相等。

Object类提供了一个equals()方法来比较两个对象的内容是否相同,因此我们可以采用这个方法去比较两个对象是否在逻辑上“相等”。如:c1.equals(c2);这里是调用从Object类继承下来的equals()方法,通过查阅API文档得到Object类里的equals方法的定义如下:

public boolean equals(Object obj)

Object这个类里面提供的Equals()方法默认的实现是比较当前对象的引用和你要比较的那个引用它们指向的是否是同一个对象,即和“c1==c2”这种写法是一样的,“c1.equals(c2)”与“c1==c2”是完全等价的。因此直接使用继承下来的equals()方法也是无法直接比较两个对象的内容是否相同的,为此,我们必须得重写equals()方法,改变这个方法默认的实现。

下面在Cat类里面重写这个继承下来的equals()方法

复制代码
 1 class Cat {
 2     int color, weight, height;
 3 
 4     public Cat(int color, int weight, int height) {
 5         this.color = color;
 6         this.weight = weight;
 7         this.height = height;
 8     }
 9     
10     /**
11      * 这里是重写相等从Object类继承下来的equals()方法,改变这个方法默认的实现,
12      * 通过我们自己定义的实现来判断决定两个对象在逻辑上是否相等。
13      * 这里我们定义如果两只猫的color,weight,height都相同,
14      * 那么我们就认为这两只猫在逻辑上是一模一样的,即这两只猫是“相等”的。
15      */
16     public boolean equals(Object obj){
17         if (obj==null){
18             return false;
19         }
20         else{
21             /**
22              * instanceof是对象运算符。
23              * 对象运算符用来测定一个对象是否属于某个指定类或指定的子类的实例。
24              * 对象运算符是一个组合单词instanceof。
25              * 该运算符是一个双目运算符,其左边的表达式是一个对象,右边的表达式是一个类,
26              * 如果左边的对象是右边的类创建的对象,则运算结果为true,否则为false。
27              */
28             if (obj instanceof Cat){
29                 Cat c = (Cat)obj;
30                 if (c.color==this.color && c.weight==this.weight && c.height==this.height){
31                     return true;
32                 }
33             }
34         }
35         return false;
36     }
37 }
复制代码

此时在再main方法里面执行打印的命令:

复制代码
 1 public static void main(String[] args) {
 2         /**
 3          * 这里使用构造方法Cat()在堆内存里面new出了两只猫,
 4          * 这两只猫的color,weight,height都是一样的,
 5          * 但c1和c2却永远不会相等,这是因为c1和c2分别为堆内存里面两只猫的引用对象,
 6          * 里面装着可以找到这两只猫的地址,但由于两只猫在堆内存里面存储在两个不同的空间里面,
 7          * 所以c1和c2分别装着不同的地址,因此c1和c2永远不会相等。
 8          */
 9         Cat c1 = new Cat(1, 1, 1);
10         Cat c2 = new Cat(1, 1, 1);
11         System.out.println("c1==c2的结果是:"+(c1==c2));//false
12         System.out.println("c1.equals(c2)的结果是:"+c1.equals(c2));//true
13     }
复制代码

这一次得到的结果就与上次没有重写equals()方法时得到的结果就不一样了:

“System.out.println(c1 == c2);”打印出来的结果依然是false,因为这里是比较两个对象的引用里面的内容,这两个引用里面的内容当然不相等,而且永远不会相等,所以打印出来的结果肯定是false

“System.out.println(c1.equals(c2));”打印出来的结果为true,因为我们在Cat类里面重写了equals()方法,改变了这个方法默认的实现,我们把方法的实现改为只要这个两个对象是真的存在,并且都是猫,并且它们的颜色(color),身高(height)和体重(weight)都相同,那么这两只猫在逻辑上就是一模一样的,是完全相同的两只猫,即这两只猫是“相等”的。所以这里打印出来的结果是true

1.3.如何比较两个字符串对象是否相等?

看下面的例子:

复制代码
1 public class TestEquals {
2     
3     public static void main(String args[]){
4         String s1 = new String("hello");
5         String s2 = new String("hello");
6         System.out.println("s1 == s2的结果是:"+(s1 == s2));//false
7         System.out.println("s1.equals(s2)的结果是:"+s1.equals(s2));//true
8     }
9 }
复制代码

这一次是比较两个字符串对象是否相等:

System.out.println(s1 == s2);

打印出来的结果依然是fase,因为这里比较的是s1s2两个字符串对象的引用,两个对象的引用永远不会相等,所以打印出来的结果为false

System.out.println(s1.equals(s2));

打印出来的结果为true,因为在String里面重写了从Object类继承(所有的类都是从Object类继承下来,String类当然也不例外,从父类继承下来就拥有了父类的一切属性与方法,所以Sting类里面也有equals()方法,并且还把这个继承下来的equals()方法重写了)下来的equals()方法,改变了这个方法默认的实现,

  在String类里面是这样重写equals()方法的实现的:用当前的这个字符串对象和指定的字符串对象比较,指定的字符串对象不能为空并且这个对象的字符序列和当前这个字符串对象的字符串序列一样,如果这些条件都满足,那么这两个字符串对象就是相等的。

因此这里的s2已经满足了条件,所以打印出来的结果是true

以后在某一个类里面比较两个对象是否相等时,首先去API文档里面查找这个类是否重写了从Object类继承下来的equals()方法。如果重写了equals()方法,那么在比较两个对象是否相等时调用的就是重写以后的equals()方法,如果没有重写,那么调用时就是直接调用从Object类里面的继承下来的那个equals()方法,并且采用equals()方法默认的实现去比较两个对象是否相等。因此每一个类都可以根据需要对从Object类继承下来的equals()方法进行重写。

  对于在API文档里面找某个类,如果一个类不用引入包就可以直接使用,那么这个类肯定是在java.lang这个包里面,如这里的String类,直接就可以使用了,所以String类一定是在java.lang这个包里面。使用某个类时看这个类引入的是哪个包,然后就去这个包里面找这个类,不用引入包的类一定是位于java.lang里面,直接去java.lang里面找就可以了。

总结:比较两个对象是否相等,我们采用equals()方法,判断两个对象是否相等的条件是由我们重写equals()方法的实现后定义的,这样就可以比较灵活地使用equals()方法在不同的类里面比较位于同一类下的两个对象是否相等了。

转载于:https://my.oschina.net/zhanghaiyang/blog/594456

相关文章:

动态规划:求最大公共子串

1 /// <summary>2 /// 动态规划&#xff1a;求最大公共子串3 /// LCS (Longest Common Subsequence)4 /// </summary>5 private static string LCS(string str1, string str2)6 { 7 var d …

java 不可最小化,java – 这是最小化绑定失效的有效方法吗?

我有一些复杂的Observable结构,这可能是也可能不是坏主意,但这不是这个问题的焦点.这些结构的问题在于它们会产生很多UI显示的Observable对象的失效.就像我所知道的那样,当JavaFX UI显示某些内容时,它在其上注册了ChangeListener,因此任何使用延迟评估的尝试都会消失.也就是说,…

让你的javascript函数拥有记忆功能,降低全局变量的使用

考虑例如以下场景&#xff1a;假如我们须要在界面上画一个圆&#xff0c;初始的时候界面是空白的。当鼠标移动的时候&#xff0c;圆须要尾随鼠标移动。鼠标的当前位置就是圆心。我们的实现方案是&#xff1a;假设界面上还没有画圆&#xff0c;那么就新创建一个&#xff1b;假设…

Maven学习总结(6)——Maven与Eclipse整合

2019独角兽企业重金招聘Python工程师标准>>> Maven学习总结(六)——Maven与Eclipse整合 一、安装Maven插件 下载下来的maven插件如下图所示&#xff1a;&#xff0c;插件存放的路径是&#xff1a;E:/MavenProject/Maven2EclipsePlugin 进入到eclipse中的dropins目录…

为python安装numpy和scipy(federo)

为了进行数值计算&#xff0c;例如积分等等&#xff0c;需要安装numpy和scipy&#xff0c;其中scipy是依赖于numpy的&#xff0c;所以先要装numpy. 1&#xff0c; 通过下载http://pypi.python.org/pypi/numpy&#xff0c;然后python set.up install安装&#xff0c;不过有些行不…

php执行mysql insert,当执行mysql insert 时插入两条是咋回事

当执行mysql insert 时插入两条是怎么回事&#xff1f;本帖最后由 Eason_____________ 于 2013-07-25 11:25:44 编辑//做了一个手机上传图片到服务器的功能。但是获取到执行insert语句时都要执行两次&#xff01;//index.phpheader("Content-Type: text/html; charsetUTF-…

产品经理要读什么书?怎么读?

产品相关知识可以在&#xff1a;http://www.aipingce.com/进行学习&#xff0c;本文转自&#xff1a;http://www.aipingce.com/article-22960-1.html 首先&#xff0c;我个人还是非常推荐大家看实体书的&#xff0c;原因如下&#xff0c;算是做个分析吧&#xff1a; 电子书是免…

HTML5:理解head

2019独角兽企业重金招聘Python工程师标准>>> HTML文档的head部分&#xff0c;通常包括指定页面标题&#xff0c;为搜索引擎提供关于页面本身的信息&#xff0c;加载样式表&#xff0c;以及加载JavaScript文件&#xff08;出于性能考虑&#xff0c;多数时候放在页面底…

php定时任务为什么不好写,php解决crontab定时任务不能写入文件问题的方法分析...

本文实例讲述了php解决crontab定时任务不能写入文件问题的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;今天使用crontab写的定时任务没有执行&#xff0c;很纳闷。crontab.phperror_reporting(0);$time date("Y-m-d h:i:s",time());file_put_conten…

SpringMVC权限管理

2019独角兽企业重金招聘Python工程师标准>>> 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet&#xff0c;所有的请求都通过DispatcherServlet。 DispatcherServlet是前置控制器&#xff0c;配置在web.xml文件中的。拦截匹配的请求&#xff0c;Servl…

搭建Hadoop集群步骤

——基于三台机器 一、前提 1、 首先要有三台已联网机器&#xff0c;假设为A&#xff0c;B1&#xff0c;B2。其中A&#xff1a;192.168.81.91&#xff1b;B1:192.168.81.92&#xff1b;B2:192.168.81.93。机器装有Ubuntu10.04服务器版64位操作系统。 2、 对三台机器做相同的处…

使用DCloud+Framework7制作移动APP应用(一)

http://my.oschina.net/kenblog/blog/516201转载于:https://www.cnblogs.com/NodeStudy/p/5223273.html

nsq php,Nsq从入门到实践

当nsq跑起来之后, 我们可能会遇到以下问题分布式部署处理错误(何时requeue)如何使用golang lib抱着不应该只停留在入门的态度, 笔者粗浅的研究了一下这几个问题, 希望也对有同样疑问的人有帮助.部署由于NSQ的分布式网络结构, NSQD必须广播(到lookup)自己的地址并让消费者连接, …

Java单元测试之JUnit4详解

2019独角兽企业重金招聘Python工程师标准>>> Java单元测试之JUnit4详解 与JUnit3不同&#xff0c;JUnit4通过注解的方式来识别测试方法。目前支持的主要注解有&#xff1a; BeforeClass 全局只会执行一次&#xff0c;而且是第一个运行Before 在测试方法运行之前运行…

Java 学习笔记 ------第二章 从JDK到IDE

本章学习目标&#xff1a; 了解与设定PATH了解与指定CLASSPATH了解与指定SOURCEPATH使用package与import管理类别初步认识JDK与IDE的对应关系一、第一个Java程序 工具&#xff1a;使用Windows自带记事本或下载其他编辑器&#xff08;推荐NotePad和Sublime&#xff09; //第一个…

Delphi中的容器类(二)

TStrings类 出于效率的考虑&#xff0c;Delphi并没有象C和Java那样将字符串定义为类&#xff0c;因此TList本身不能直接存储字符串&#xff0c;而字符串列表又是使用非常广泛的&#xff0c;为此Borland提供了TStrings类作为存储字符串的基类&#xff0c;应该说是它除了TList…

Java怎么把数组怎么放入set,如何将数组转换为Java中的Set

回答(16)2 years ago我从上面的建议中写下了以下内容 - 偷了它......真好&#xff01;/*** Handy conversion to set*/public class SetUtil {/*** Convert some items to a set* param items items* param works on any type* return a hash set of the input items*/public s…

vue组件定义、组件的切换、组件的通信、渲染组件的几种方式(标签、路由、render)...

vue中全局的概念是什么&#xff1f;---就是全局定义的功能&#xff0c;所有实例化的vm都可以使用&#xff0c; 全局定义的是挂在构造函数Vue上面的&#xff0c;所以实例化出的对象都可以使用这个功能 1、什么是组件&#xff1f;---从UI的角度把页面拆分成不同的部分&#xff0…

JS九九乘法表

来一个老生常谈的话题--九九乘法表&#xff0c;哈哈&#xff0c;好久不写了呢 <!DOCTYPE html> <html> <head lang"en"><meta charset"UTF-8"><title></title><style>th{border: #ccc 1px solid;font-weight: n…

Php Fatal error: Allowed memory size of 33554432 bytes exhausted 的解决办法

Php Fatal error: Allowed memory size of 33554432 bytes exhausted 的解决办法 在 php.ini 配置文档里面&#xff0c;默认的memory_limit 属性值为32M &#xff0c;值设置得太小了而导致这个问题的出现。 解决这个问题&#xff0c;我们一般有三种方式&#xff1a; 1、修改PHP…

php 自加 性能,对于数据库的自增、自减心得

系统研发过程中会有很多地方涉及到自增、自减操作 如&#xff1a;加入版块时&#xff0c;用户版块数自增1&#xff0c;版块用户数自增1&#xff1b;退出版块时&#xff0c;用户版块数要减1&#xff0c;版块用户数也要减1这里推荐&#xff1a;1.自增可以用2.自减不要用&#xff…

Linux rsync目录同步功能实现

实现目标:A 服务器上 /opt/web 目录,与B服务器上 /opt/web目录实现同步。即&#xff1a;B主动与A进行同步。OS: Reaht AS4A Server 192.168.1.2 /opt/webB Server 192.168.1.3 /opt/web一. A Server config1.rsync 系统自带, 需要使用 --deamon 方式进行启动,服务端口是 TCP …

宏定义的布局约束

*自适应向布局约束的转化关闭*/ #define PREPCONSTRAINTS(VIEW) [VIEW setTranslatesAutoresizingMaskIntoConstraints:NO] #define CONSTRAIN(PARENT, VIEW, FORMAT) [PARENT addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:(FORMAT) options:0 metrics:nil…

项目中WebService使用Spring容器的配置

<context:component-scan base-package"com.huawei.support"> <context:include-filter type"annotation" expression"org.aspectj.lang.annotation.Aspect" /> </context:component-scan> 扫描采用注解…

java 静态代码块 多线程,Java多线程编程笔记10:单例模式

立即加载&#xff1a;“饿汉模式”立即加载就是指使用类的时候已经将对象创建完毕&#xff0c;常见的实现方法就是直接new实例化。也就是在调用方法前&#xff0c;实例就被创建了。示例代码如下所示&#xff1a;class MyObject{private static MyObject myObjectnew MyObject()…

创业笔记-Node.js入门之阻塞与非阻塞

阻塞与非阻塞 正如此前所提到的&#xff0c;当在请求处理程序中包括非阻塞操作时就会出问题。但是&#xff0c;在说这之前&#xff0c;我们先来看看什么是阻塞操作。 我不想去解释“阻塞”和“非阻塞”的具体含义&#xff0c;我们直接来看&#xff0c;当在请求处理程序中加入阻…

vs 添加ico图 到资源

有时候想用自己做的ico 文件作为程序的图标来取代VS 程序默认的图标&#xff1b;在VS2005 资源视图中&#xff0c;打开Icon 上右击-->Add resource -->Import -->选择自己的ico 文件会跳出个错误框&#xff0c;说VS不支持32 位彩色图片&#xff1b; 网上搜索说VS不支…

HIVE QL 杂记

最近要处理用户访问日志&#xff0c;需要从HIVE中取数据&#xff0c;写了一些HIVE QL&#xff0c;有一点小感想&#xff0c;记录在此。 1. 临时表 在HIVE中进行多表连接时&#xff0c;可以给一些临时表命名&#xff0c;这样有助于理清查询语句之间的逻辑&#xff0c;格式为&…

java和内存交互,java内存模型-内存间交互操作

前言本文是阅读周志明大佬的《深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践(第3版)》第12章&#xff0c;12.3节Java内存模型得来的读书笔记。阅读告警&#x1f602;&#x1f602;&#x1f602;&#xff0c;本文可能会有点枯燥&#xff0c;大部分内容都是对书中内容做一…

文件读写io操作范例

系统io读写&#xff0c;copy int main(int argc, char **argv) { if(argc ! 3) { printf("Usage: %s <src> <dst>\n", argv[0]); exit(0); } int fd1, fd2; fd1 open(argv[1], O_RDONLY); fd2 open(argv[2], O_CREAT | O_TRUNC | O_WRONLY); if(…