zoukankan      html  css  js  c++  java
  • Java中equals与==异同

    为了更好的理解,先来看看java的数据类型
    java的数据类型分为两大类:基本数据类型 与 引用数据类型

    基本数据类型有8种
    数值型:byte int short long
    字符型:char
    布尔型:bool

    引用数据类型有3种:
    类:Class
    接口:Interface
    数组:Array

    再有,基本数据类型也有与自己相对应的封装类,即引用类型:
    数值 :Byte、Short、Integer、Long、Float、Double
    字符:Character
    布尔:Boolean

    在java中基本数据类型都被统一放在一块区域(内存的栈中),其中有一部分区域称之为“常量池”
    在常量池中,基本数据类型可以被共享,也就是说我们定义一个int a = 5;然后又定义了一个int b = 5;这时a与b在内存中指向的是同一个5。
    而对于引用数据类型来说,一个引用数据类型的变量保存的就是这个引用数据类型的引用,即地址。如:String s = “abc” s保存的就是一个地址。

    好了 现在进入正题: equals与==的区别
    简单来说:equals比较的是值,==比较的是地址。带着这样的前提会帮你理解下面的废话…

    看下面一段代码:

    1 String s1 = new String("abc");
    2 String s2 = "abc";
    3 if(s1 == s2){
    4   System.out.println("s1 == s2");
    5 }
    6 if(s1.equals(s2)){
    7   System.out.println("s1 equals s2");
    8 }

    输出结果是:“s1 equals s2”。这是为什么?,s1与s2明明都是"abc"呀,难道“s1 != s2”吗。

    事情是这个样子的:
    虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。对于第一种,jvm会马上在heap中创建一个String对象,然后将该对象的引用返回给用户。对于第二种,jvm首先会在内部维护的strings pool(可以称之为字符串池)中通过String的 equels 方法查找是strings pool中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果strings pool中没有该String对象,jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法:str.intern();

    intern是这样工作的:首先查看strings pool中有无“abc”对象的引用,有则返回那个”abc”的引用。没有,则在堆中新建一个对象,然后将新对象的引用加入到strings pool中。

    是不是很眼熟,没错,这不就是刚刚第一个代码例子中 String s2 = “abc”;的时候jvm所做的事情么。所以说,用String来声明字符串,结果都会至少有一个String对象存在的。
    与之对应的基本数据类型的封装类有一些也具有常量池技术:
    这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。并且Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。

    明白原理之后回头再看看:
    来看看==:
    通常可以这样定义一个变量:int a = 1; int b = 1;
    a与b都是基本数据类型,会被放在常量池中,而且此时因为java的常量池共享,此时常量区中只有一个1,所以if(a == b)返回位true。因为a和b的无论是值还是地址都是相等的。(这里不能用equals比较,因为equals是Object类的方法。)

    现在看看equals:
    上面说了,equals是继承自Object类的一个方法,所以所有引用类型都可以使用equals方法。
    然后记住:声明一个类的实例,要用new关键字 ,所以String str1 = “hello world”;String str2 = “hello world”; 这两个肯定是相等的,因为没有用到new 所以java虚拟机会与处理基本类型一样,去常量池查看是否已存在一个”hello world”,如果有则不再新增,str1,str2都指向这个”hello world”。
    我们可以用new关键字这样实例化一个String对象:String s1 = new String(“abc”) ; String s2 = new String(“abc”)。
    s1 与 s2 是引用数据类型 所以if(s1.equals(s2))返回的是true,而if(s1 == s2)则返回false。这是因为s1与s2都是有用new关键字声明出的新对象,各自有各自的地盘,互不相干。虽然值是一样的,但是存储的位置却不一样,就好像一个楼里有两个同名的人,但是两人住不是一个房间,你对其一操作,不会影响另一个。所以==所比较出的是地址是否相同。当然是false了。
    这也证实了开始说的:equals比较的是值,==比较的是地址。

    另外:Object类中的equals方法,其代码就是==操作。在没有复写Object的equals方法时调用的话,其实就是使用==。固有的引用数据类型已经复写了equals方法,如String类。

    Object类中的equals方法:

    1 public boolean equals(Object obj) {
    2     return (this == obj);
    3 }
     
  • 相关阅读:
    delphi datetimepicker 修改时间无效问题
    C#写入文件
    C# winform中listview排序
    C/C++,python,java,C#月经贴问题
    Redis Sentinel 原理简单介绍
    JVM垃圾收集 知识汇总
    Java HotSpot VM Options
    Spring三级缓存解决循环依赖
    Markdown基础用法
    join示例分析
  • 原文地址:https://www.cnblogs.com/lipijin/p/3064425.html
Copyright © 2011-2022 走看看