【Java基础】“equals” 和 “==”的理解

简述:
==: 用于基本类型和引用类型:当用于基本类型时候,是比较值是否相同;当用于引用类型的时候,是比较对象(内存地址)是否相同;
equals: java.lang包中的Object类有public boolean equals(Object obj) { return (this == obj) }方法,它比较两个对象是否相等;

故对于引用类型在一定程度上,"==" 和 "equals"的功能是一致的,都是比较对象(内存地址)是否相同;

1、JDK常用类的“==”和“equals()”的区别:

JDK中常用类String、基础类型的封装类型都重写了equals()方法,故才有下例的中的结果:

//String重写了Object的equals()方法,比较相同index的字符是否一致(基础类型char的比较"==")
//同时也发现基础类型的封装类型,同样也重写了equals()方法,故平时使用时equals()给我们的印象是比较本身的值是否相同;
//char[Character], byte[Byte], short[Short], int[Integer], long[Long], float[Float], double[Double], boolean[Boolean]
String a = new String("s");
String b = new String("s");
System.out.println(a.equals(b));//print true
System.out.println(a == b);//print false

故在引用类型的比较上,个人感觉equals()方法是对“==”的补充,完成“==”做不到的功能(比较对象的内容是否相同)!

2、String类中“==”的细节:

对于引用类型,“==”比较对象(内存地址)是否相同,但是下例中的结果却并不完全遵循上述的描述:

String a = new String("s");
String c = "s";
String d = "s";
System.out.println(c == d); //print true
System.out.println(c == a); //print false

其原因:在JVM内,存在字符串池,其中保存着很多 String对象,并且可以被共享使用。

其过程:如果要创建下一个字符串对象,JVM首先会到字符串池中寻找,是否存在对应的字符串对象,如果存在,则返回一个己存在对象的对象的引用给要创建的对象引用.

如果不存在,才会创建一个新的对象,并返回一个新对象的对象引用给要创建的对象引用。故例子中 c == d返回值是true。

而对于 String a = new String("s"),共有“s”, a两个String对象,且a是不存放到字符串共享池中的,故例子中c == a返回值是false

上述的描述同样适用于Integer等基础类型的封装类;

3、普通类的“equals()”重写:

受到String类的启发,我们也可以来重写自定义类的equals()方法,如下例:

public class Equals {
    private String name = "";
    private int age = 0;
    public Equals(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        if(obj instanceof Equals){
            Equals equ = (Equals) obj;
            return this.name.equals(equ.name) && this.age == equ.age;
        }
        return false;
    }
    @Override
    public int hashCode() {
        return 31 * this.name.hashCode() + ((Integer)this.age).hashCode();
    }
    public static void main(String[] args) {
        Equals eq1 = new Equals("s", 3);
        Equals eq2 = new Equals("s", 3);
        System.out.println(eq1.equals(eq2));
        System.out.println(eq1 == eq2);
    }
}

重写equals必须注意:
1. 自反性:对于任意的引用值x,x.equals(x)一定为true
2. 对称性:对于任意的引用值x 和 y,当x.equals(y)返回true,y.equals(x)也一定返回true
3. 传递性:对于任意的引用值x、y和 z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回 true
4. 一致性:对于任意的引用值x 和 y,如果用于equals比较的对象信息没有被修改, 多次调用x.equals(y)要么一致地返回true,要么一致地返回false
5. 非空性:对于任意的非空引用值x,x.equals(null)一定返回false
6. 重写hashCode:最好同时重写hashCode()方法,否则两个等价的对象可能得到不同的hashCode值,导致使用集合框架出现问题;

hashCode介绍:JDK根据对象的地址或者字符串或者数字算出来的int类型的数值,此方法主要是为了提高哈希表(例如 java.util.Hashtable提供的哈希表)的性能;

通过分析Hashtable的get()方法可以看出key键要同时满足hashCode值、key值,才能获得对应的value键;

public Object get(Object key) {
    HashtableEntry e;
    HashtableEntry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;

    for (e = tab[index]; e != null; e = e.next)
        if ((e.hash == hash) && e.key.equals(key))
            return e.value;
        return null;
}        
时间: 2024-10-10 08:17:37

【Java基础】“equals” 和 “==”的理解的相关文章

Java基础12:深入理解Class类和Object类

Java基础12:深入理解Class类和Object类 Java中Class类及用法 Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI. 这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类.Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建. 说白了就是: Class类也是类的一种,只是名字和class关键字高度相似.Java是大小写敏感的语言.

Java基础3:深入理解String及包装类

Java基础3:深入理解String及包装类 String的连接 @Testpublic void contact () {    //1连接方式    String s1 = "a";    String s2 = "a";    String s3 = "a" + s2;    String s4 = "a" + "a";    String s5 = s1 + s2;    //表达式只有常量时,编译

Java基础1:深入理解Java面向对象三大特性

Java基础1:深入理解Java面向对象三大特性 三大特性:继承 封装 多态 继承 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类. 子类拥有父类非private的属性和方法. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展. 子类可以用自己的方式实现父类的方法 Java中的继承只能单继承,但是可以通过内部类继承其他类来实现多继承. public class Son extends Father{publi

Java基础8:深入理解内部类

Java基础8:深入理解内部类 内部类初探 一.什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和缺省的包访问权限).内部类主要有以下几类:成员内部类.局部内部类.静态内部类.匿名内部类 二.内部类的共性 (1)内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 . (2)内部类不能用普通

《Java架构筑基》从Java基础讲起——深入理解Finial

一.final关键字概述 1. 为什么会有final 由于继承中有一个方法重写的现象,而有时候我们不想让子类去重写父类的方法.这对这种情况java就给我们提供了一个关键字: final 2. final概述 final关键字是最终的意思,可以修饰类,变量,成员方法. 3. final修饰特点 修饰类: 被修饰类不能被继承 修饰方法: 被修饰的方法不能被重写 修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实是一个常量 4. final关键字修饰局部变量 基本类型,是值不能被改变 引用类型,是

Java基础-equals方法

Object类中的equals方是用来判断一个对象等于另一个对象,至于这个等于的条件需要,比如说,String类的equals相等的条件就是字符串的内容必须相同,equals方法返回的值才为true.所以在我们在自己定义的类中,equals的重写是常见的!这里主要展示equals的特性和equals的正确写法,至于equals方法具体的含义这里不介绍! 1. 举一个例子 在这介绍其他的,我们先来看看正确的写法 public class Animal { private String name =

java基础4:深入理解final关键字

本文主要介绍了final关键字的使用方法及原理 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 文章首发于我的个人博客: https://h2pl.github.io/2018/04/23/javase4 final关键字可以修饰类.方法和引用. 修饰类,该类不能被继承.并且这个类的对象在堆中分配内存后地址不可变. 修饰方法,方法不能被子类重写. 修饰引用,引用无法改变,对于基本类型,无法修改值,对于引用,虽然不能修改地址值,但是可以对指向对象

《Java架构筑基》从Java基础讲起——深入理解Static

1. static的作用和特点 可以用来修饰:成员变量,成员方法,代码块,内部类等.具体如下所示 修饰成员变量和成员方法 被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用. 被static 声明的成员变量属于静态成员变量,静态变量存放在Java内存区域的方法区. 静态代码块 静态代码块定义在类中方法外,静态代码块在非静态代码块之前执行(静态代码块->非静态代码块->构造方法) 该类不管创建多少对象,静态代码块只执行一次. 静态内部类(

【java基础之异常】死了都要try

目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常throws 2.4 捕获异常try…catch 2.4 finally 代码块 2.5 finally 代码块与return语句 2.6 异常注意事项 3.自定义异常 3.1 概述 3.2 自定义异常练习 4.来!和异常大干一场 @ 1.异常 1.1 异常概念 异常 :简单说就是不正常运行,最终导致JVM

【转载】Java基础之String中equals,声明方式,等大总结

转载请注明出处:http://blog.csdn.net/dmk877/article/details/49420141 无论你是一个编程新手还是老手,提到String你肯定感觉特别熟悉,因为String类我们在学习java基础的时候就已经学过,但是String类型有我们想象的那么简单吗?其实不然,String类型的知识点还是比较多的.今天就和大家来一起讨论一下,关于String的一些容易让人疑惑的地方,废话不多说进入正题...如有谬误请批评指正,如果有疑问请留言.我会在第一时间修改或回答 通过