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 }
     
  • 相关阅读:
    arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
    arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
    arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
    arcgis api 3.x for js 入门开发系列五地图态势标绘(附源码下载)
    arcgis api 3.x for js 入门开发系列四地图查询(附源码下载)
    Java里面获取当前服务器的IP地址
    Flutter at Google I/O 2018
    Modbus RTU 协议使用汇总
    plsql 创建表空间、用户、赋予权限
    Oracle:ODP.NET Managed 小试牛刀
  • 原文地址:https://www.cnblogs.com/lipijin/p/3064425.html
Copyright © 2011-2022 走看看