“==” 操作符 与 equals 方法的区别,toString

导读:本篇文章讲解 “==” 操作符 与 equals 方法的区别,toString,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

“==” 操作符 与 equals 方法的区别,toString

在这里插入图片描述


每博一文案

读过这样一段话:很多人都羡慕我的坚强独立,夸赞我的善解人意。无论什么事情,
我都会把别人放在首位,宁愿自己吃亏,也会尽力满足别人的需求,其实,如果可以,我也想活得任性一点,
可以不用微笑代替内心的无奈,不用小心翼翼顾及所有人,是啊,生活中不乏,这样的人,因为太重感情,伤害了自己,
一面懊悔自的同时,一面有继续无条件包容,傻的让人心疼,常常为了别人委屈了自己,却得不到同样的珍惜。
一腔热情换来了忽视和冷漠,温柔过了头,连拒绝别人都觉得是自己做错了事。
总是对别人细微的好意,掏心掏肺,却怎么努力也换不回真心相对,但偏偏感情里总是投入越多的人,越容易让自己受伤,等到
真心被辜负,才真正醒悟,然后默默叮嘱自己,下一次别再这么傻了。
生命来来往往,人情冷暖自知,也许不高估自己和任何人的关系,就是避免受伤和失望的最好方法。
余生把自己看重要点,也把别人看轻,愿你有大胆爱的勇气,更要有放下爱的魄力,看尽世间沧桑,内心安然无恙。
                                                   ——————   一禅心灵庙语


1. == 操作符

  1. == 是操作符,不是方法,可以直接使用
  2. == 是操作符,可以使用在基本数据类型 和 引用数据类型变量中
  3. 如果比较的是基本数据类型变量,比较判断的是 两个数据的值是否相等,
  4. 如果比较的是引用数据类型变量,比较判断的是 两个对象的地址是否相同,即两个引用是否指向同一个对象的实体。
  5. 特使的 String 字符串常量池。
  6. == 符合使用时,必须保证符合左右两边的变量类型一致,包括 “自动转换”
  • 基本数据类型比较判断数值是否相等
package blogs.blog1;

public class blog1 {
    public static void main(String[] args) {
        int i = 10;
        int j = 10;
        double d = 10.0;

        System.out.println(i == j);  // true
        System.out.println(j == d);  // true
    }
}

在这里插入图片描述


public class blog1 {
    public static void main(String[] args) {
        int i = 9;
        char c = 9;

        System.out.println("c == i: "+(c == i));

        char A1 = 'A';
        char A2 = 65;

        System.out.println("A1 == A2: "+(A1 == A2));

        char a1 = 'a';
        char a2 = 97;

        System.out.println("a1 == a2: "+(a1 == a2));
    }
}

在这里插入图片描述


  • 引用数据类型的比较判断,比较判断的是:引用类型的地址是否相等
package blogs.blog1;

public class blog1 {
    public static void main(String[] args) {
        Animal a1 = new Animal("Tom",18);
        Animal a2 = new Animal("Alice",18);
        Animal a3 = new Animal("Tom",18);

        System.out.println("a1: "+a1);
        System.out.println("a2: "+a2);
        System.out.println("a3: "+a3);

        System.out.println("a1 == a2: "+(a1 == a2)); // 引用类型比较的是两个地址是否相等
        System.out.println("a2 == a3: "+(a2 == a3));
        
    }
}

class Animal{
    public String name ;
    public int age;

    public Animal() {
        // 无参构造器
    }

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }



}



在这里插入图片描述


  • 特殊的 String 字符串引用类型,== 操作符的比较,没有使用 new 的和使用 new 的
public class blog1 {
    public static void main(String[] args) {
        String s1 = new String("Tom");
        String s2 = new String("Tom");
        String s3 = new String("Alice");

        System.out.println("s1: "+s1);
        System.out.println("s2: "+s2);
        System.out.println("s3: "+s3);

        // String 使用了 new 的方式创建 对象,== 比较的是地址,没有字符串常量池
        System.out.println("s1 == s2: "+(s1 == s2));
        System.out.println("s2 == s3: "+(s2 == s3));
    }
}

在这里插入图片描述


不使用 new 创建字符串String 比较的是 字符串的内容,使用的是字符串常量池 ,== 可以比较字符串的内容,这个是字符串常量池的存在的特殊性质。

public class blog1 {
    public static void main(String[] args) {
        String s1 = "Tom";
        String s2 = "Tom";
        String s3 = "Alice";

        System.out.println("s1 == s2: "+(s1 == s2));
        System.out.println("s2 == s3: "+(s2 == s3));
    }
}

在这里插入图片描述


2. Object.equals 方法

  1. equals() 是 Object类中的一个方法,所有类都继承了这个方法。所以只有类才可以直接使用,不是类无法使用其方法。
  2. equals() 只适用于引用数据类型,因为 equals() 是 Object 类中的一个方法而已,基本数据类型无法调用 Object 中的方法(包装类可以)
  3. Object 类中 equals()的定义:比较的是 地址 。如下:
public boolean equals(Object obj) {
        return (this == obj);
    }

package blogs.blog1;

public class blog1 {
    public static void main(String[] args) {
        Animal a1 = new Animal("Tom",18);
        Animal a2 = new Animal("Tom",18);
        Animal a3 = new Animal("Alice",18);
        System.out.println(a1.equals(a2));
        System.out.println(a1.equals(a3));
        
    }
}

class Animal{
    public String name ;
    public int age;

    public Animal() {
        // 无参构造器
    }

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }



}


在这里插入图片描述

说明 Object 定义的 equal() 和 == 的作用是一样的:比较的是对象的地址,是否指向同一个对象。

  1. 不过像 String,Date,File 以及包装类等重写了 Object 类中的 equals() 方法,重写以后,比较的就不是两个引用的地址了。而是比较两个对象的实体内容的值是否相同,具体的根据实际情况比较判断。

如下是 String 重写的 equals() 方法

public boolean equals(Object anObject) {
        if (this == anObject) {  // 判断两个对象是否指向同一个地址,是不用比较判断了,直接返回true,因为指向的都是
            return true;         // 同一个地址的,内容当然是一样的了。
        }
        if (anObject instanceof String) {  // 判断anObject 是否是 String的实例/子类,
            String anotherString = (String)anObject;   // 是强制向下转型
            int n = value.length;
            if (n == anotherString.value.length) {     // 判断长度是否相等,再进一步比较
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {                    // 从后往前,一一比较判断是否相等,凡有一个不相等,返回fasle
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
public class blog1 {
    public static void main(String[] args) {
        String s1 = "Tom";
        String s2 = "Tom";
        String s3 = "Alice";

        String s4 = new String("Tom");
        String s5 = new String("Tom");
        String s6 = new String("Alice");

        System.out.println("s1.equals(s2): "+(s1.equals(s2)));
        System.out.println("s1.equals(s3): "+(s1.equals(s3)));
        System.out.println("s4.equals(s5): "+(s4.equals(s5)));
        System.out.println("s4.equals(s6): "+(s4.equals(s6)));

    }
}

在这里插入图片描述


如下是 Date 重写的 equals()方法,需要注意的是 Date 是在 import java.util.Date; 包下的不是 sql包下的

public boolean equals(Object obj) {
        return obj instanceof Date && getTime() == ((Date) obj).getTime();
    }

public long getTime() {
        return getTimeImpl();
    }

private final long getTimeImpl() {
        if (cdate != null && !cdate.isNormalized()) {
            normalize();
        }
        return fastTime;
    }
public class blog1 {
    public static void main(String[] args) {
        Date d1 = new Date(32432525324L);
        Date d2 = new Date(32432525324L);
        Date d3 = new Date(92432525329L);

        System.out.println("d1.equals(d2): "+(d1.equals(d2)));
        System.out.println("d1.equals(d3): "+(d1.equals(d3)));
    }
}

在这里插入图片描述


  1. 通常情况下,我们自定义的类如果使用equals()的话,重写 equals()方法通常是比较两个对象的 “实体内容” 是否相同,那么我们就需要重写 Object 类中的 equals()方法了。
  2. 注意不要让左值为 null;调用该方法。null.equals() 尽可能让左值为确定值,不要为 null,防止null引用的出现,其中的 equals(null) 参数可以为 null,返回的是 false

2.1 重写 Object.equals() 方法

对于定义的类/没有重写 equals()方法的类,需要我们自己根据需求进行 equals()方法的重写:

一般重写的 equals()方法,比较的都是对应类中的属性的值的内容的,不是比较的地址。

重写equals()方法的一些原则

  • 对称性: 如果 X.equals(Y) 返回的是 true;那么Y.equals(X) 也应该返回的是 true;而不是反过来比较结果就不一样了。
  • 自反性: X.equals(X) 必须返回 true,自己和自己比较判断,必须返回 true;
  • 传递性: 如果 X.equals(Y) 返回的是 true,而且 Y.equals(Z) 返回的是 true,那么 Z.equals(X) 也应该返回的是 true
  • 一致性: 如果 X.equals(Y) 返回的是 true,只要 X 和 Y 内容一直不变,不管重复执行多少次 X.equals(Y) ,都应该返回 true,不会因为多个执行的而结果不一致
  • 任何情况下:X.equals(null) 永远返回的都是 false 。以及 X.equals() 和 X 不同类型的对象永远返回的都是 false

如下我们重写自己定义的 Animal 类比较其中的属性的值内容,而不是地址。

我们可以仿照 String 类重写的 equals()方法。重写我们自己定义的 Animal 类。

如下是 String 重写 equals()方法的代码

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

如下我们仿写的 equals()方法

class Animal{
    public String name ;
    public int age;

    public Animal() {
        // 无参构造器
    }

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }

    // 重写 Object中的 equals()方法
    @Override
    public boolean equals(Object object) {
        if(this == object) {  // 判断是否指向同一个地址,是直接返回 true
            return true;
        }
        
        if(object instanceof Animal) {   // 判断object 是否是该 Animal的实例/子类
            Animal animal = (Animal) object;  // 强制向下转型
            
            // 判断其中Animal 类中的 age,name 属性的内容是否一致
            return this.age == animal.age && this.name.equals(animal.name);
        } else {  // 都不是实例了,不用比了,返回 fasle
            return false;
        }
    }
    
}

在这里插入图片描述

调用重写的 equals()方法进行比较判断

public class blog1 {
    public static void main(String[] args) {
        Animal a1 = new Animal("Tom",18);
        Animal a2 = new Animal("Tom",18);
        Animal a3 = new Animal("Alice",18);
        System.out.println("a1.equals(a2): "+(a1.equals(a2)));
        System.out.println("a1.equals(a3): "+(a1.equals(a3)));

    }
}

在这里插入图片描述

使用我们重写的 equals()方法就不再调用父类 Object.equals()方法了,而是调用我们重写的 equals()比较的就是 Animal 类中的属性的内容了,当内容一致时返回的就是 true


2.2 IDEA 快捷重写 equals()方法

这里告诉大家一个好消息,我们一般都不用手动重写 equals() 方法,IDEA可以自动帮我们重写 equals()方法,而且写的还比我们自己写的更加好,代码更加健壮。基于这些原因,一般我们都是使用 IDEA自动生成重写的 equals()方法。

具体操作如下:

  1. 可以使用快捷键 Alt+Insert 或者鼠标右键,选择Generate...(该单词是:产生的意思) 这个选项。如果快捷键没有用的话,可能需要配合 Fn 功能键一起使用。

在这里插入图片描述


  1. 弹出如下 Generate 窗口,点击 equals() and hashCode() 选项,该选项表示会自动重写 equals() 和 hashCode()方法

在这里插入图片描述


  1. 在再弹出窗口中,选择你所需要的 JDK 版本。这里我们可以选择:java.util.Objects.equals and hashCode(java7+) 这个选项,再 next.

在这里插入图片描述


  1. 重写的 equals() 方法勾选你要比较判断的属性名,如下,点击 next

在这里插入图片描述


  1. 这里是重写 hashCode()方法勾选对应包含的属性名,点击 next

在这里插入图片描述

  1. 所有非空 null 的表示方式,我们也可以勾选上,最后 Finish 就自动生成好了
    在这里插入图片描述

  2. 如下就是 IDEA 中帮我们自动重写的 equals() 和 hashCode() 方法

在这里插入图片描述


3. == 操作符 与 equals 方法的区别

  1. == 是操作符,不是方法可以直接使用,既可以 比较基本数据类型也可以比较引用数据类型。不过对于基本数据类型比较的是内容值,而对于引用数据类型比较的就是内存的地址了。
  2. equals() 是方法需要类调用,它是属于java.lang.Object 类里面的方法,如果该方法没有被重写过,默认也是 == ,我们可以看到 String ,Date ,File 包装类等的 equals() 方法是被重写了的,而且 String 类在日常开发中用的比较对多,久而久之,形成了 equals() 是比较值的错误观点
  3. 对于 equals() 比较的究竟是地址,还是属性内容值,具体的要看自定义的类有没有重写 Object 的 equals() 方法来判断。
  4. 通常情况下,重写的 equals() 方法,比较的是类当中相应的属性内容是否相等。

4. toString 方法

  1. toString() 方法在Object类中定义,其返回值是 String 类型,返回类名和它的引用地址。当我们输出对象的引用时,实际上就是调用是当前对象 Object.toString()的方法。

如下:

package blogs.blog1;

import java.util.Date;
import java.util.Objects;

public class blog1 {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println("animal: "+animal);
        System.out.println("animal: "+animal.toString());
    }
}

class Animal{
    public String name ;
    public int age;

    public Animal() {
        // 无参构造器
    }

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }

}

在这里插入图片描述


如下是 Object.toString 方法的源代码:

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
  • getClass() 返回的是类所在的包的路径
  • getClass().getName() 返回的是类名
  • hashCode() 哈希码值
  • animal.getClass().getSuperclass() 返回的是对于类的父类的值。
public class blog1 {
    public static void main(String[] args) {

        Animal animal = new Animal();

        System.out.println("animal: "+animal);
        System.out.println("animal: "+animal.toString());

        System.out.println("animal.getClass(): "+(animal.getClass()));
        System.out.println("animal.getClass().getName(): "+animal.getClass().getName());
        System.out.println("animal.hashCode():"+Integer.toHexString(animal.hashCode()));
        System.out.println("animal.getClass().getSuperclass(): "+animal.getClass().getSuperclass());

    }
}

在这里插入图片描述


如下是 public println( ) 方法的源代码

public void println(Object x) {
        String s = String.valueOf(x);  // 调用该方法将返回值转换为ValueOf()包装类字符串
        synchronized (this) {
            print(s);
            newLine();
        }
    }

public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();  // 如果 obj==null返回 null,否则返回toString()
    }

  1. 可以根据需要在用户自定义类型中重写 toString()方法,如:“String,Date,File ” 包装类都重写了 toString ()方法。

如下是:String 重写 toString 的方法

public String toString() {
    return this;
}
public class blog1 {
    public static void main(String[] args) {
        String s1 = "Tom";

        System.out.println(s1);   // s1对象打印调用的就是 重写的toString()方法
        System.out.println(s1.toString());  // 重写了toString()方法不再是Object.toString()中的方法了
    }
}

在这里插入图片描述


如下是 Date 重写toString 的方法的源代码,注意的是 Date 是在 import java.util.Date; 包下的,不是 sql包下的

public String toString() {
        // "EEE MMM dd HH:mm:ss zzz yyyy";
        BaseCalendar.Date date = normalize();
        StringBuilder sb = new StringBuilder(28);
        int index = date.getDayOfWeek();
        if (index == BaseCalendar.SUNDAY) {
            index = 8;
        }
        convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd

        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
        TimeZone zi = date.getZone();
        if (zi != null) {
            sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
        } else {
            sb.append("GMT");
        }
        sb.append(' ').append(date.getYear());  // yyyy
        return sb.toString();
    }
import java.util.Date;
import java.util.Objects;

public class blog1 {

    public static void main(String[] args) {
        Date date = new Date(32432525324L);
        System.out.println(date);  // 打印date 就是调用重写的toString()方法
        System.out.println(date.toString());
    }
}

在这里插入图片描述


  1. 对于我们自定的类,如果没有重写 toString()方法 ,pritnt(类名)或者print(类名.toString()) 都是调用的是Object默认的 toString()方法。所以为了需要我们一般都重写 toString()方法。

5. 重写 toString 方法

自定义类也可以重写toString()方法,当调用方法时,返回对象的: “实体内容”;

在这里插入图片描述

如下我们手动重写子自定义的Animal中的 toString ()方法。如下

class Animal{
    public String name ;
    public int age;

    public Animal() {
        // 无参构造器
    }

    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override 
    public String toString() {
        return "name: "+ this.name +"age: "+this.age;
    }
}

public class blog1 {
    public static void main(String[] args) {
        Animal animal = new Animal("Tom",18);
        System.out.println("animal: "+animal);
        System.out.println("animal.toString(): "+animal.toString());

    }
}

在这里插入图片描述


3.1 IDEA 快捷重写 toString() 方法

和 equals() 方法一样,IDEA是由快捷键,自动为我们生成重写的 toString()方法。重写toString() 是比较简单的,所以一般我们都是使用IDEA自动生成重写的方法。如果不符合条件,再进行一个修改就可以了。

具体操作如下:

  1. 可以使用快捷键 Alt+Insert 或者鼠标右键,选择Generate...(该单词是:产生的意思) 这个选项。如果快捷键没有用的话,可能需要配合 Fn 功能键一起使用。

在这里插入图片描述


  1. 弹出如下 Generate 窗口,点击 toString() 选项,该选项表示会自动重写 toString()方法

在这里插入图片描述


  1. 弹出如下 Generate toString() 窗口,其中会显示对应类中的所有属性名,可以根据需要使用 Shift / Ctrl 选择你要想打印显示的属性名。最后点击 OK

在这里插入图片描述


在这里插入图片描述


6. 总结:

  1. == 是操作符可以直接使用,如果是基本数据类型比较的是内容值,如果是引用类型,比较的的地址是否相等,特殊的 String 存在字符串常量池,比较的是内容值
  2. equals()方法, 默认 Object 类中的比较的是地址是否相等,所以一般是需要重写的。
  3. 注意 == 与 equals() 方法的区别
  4. toString() 方法的使用,重写

7. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,江湖再见,后会有期!!!


在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82998.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!