“==” 操作符 与 equals 方法的区别,toString
每博一文案
读过这样一段话:很多人都羡慕我的坚强独立,夸赞我的善解人意。无论什么事情,
我都会把别人放在首位,宁愿自己吃亏,也会尽力满足别人的需求,其实,如果可以,我也想活得任性一点,
可以不用微笑代替内心的无奈,不用小心翼翼顾及所有人,是啊,生活中不乏,这样的人,因为太重感情,伤害了自己,
一面懊悔自的同时,一面有继续无条件包容,傻的让人心疼,常常为了别人委屈了自己,却得不到同样的珍惜。
一腔热情换来了忽视和冷漠,温柔过了头,连拒绝别人都觉得是自己做错了事。
总是对别人细微的好意,掏心掏肺,却怎么努力也换不回真心相对,但偏偏感情里总是投入越多的人,越容易让自己受伤,等到
真心被辜负,才真正醒悟,然后默默叮嘱自己,下一次别再这么傻了。
生命来来往往,人情冷暖自知,也许不高估自己和任何人的关系,就是避免受伤和失望的最好方法。
余生把自己看重要点,也把别人看轻,愿你有大胆爱的勇气,更要有放下爱的魄力,看尽世间沧桑,内心安然无恙。
—————— 一禅心灵庙语
文章目录
1. == 操作符
==
是操作符,不是方法,可以直接使用==
是操作符,可以使用在基本数据类型 和 引用数据类型变量中- 如果比较的是基本数据类型变量,比较判断的是 两个数据的值是否相等,
- 如果比较的是引用数据类型变量,比较判断的是 两个对象的地址是否相同,即两个引用是否指向同一个对象的实体。
- 特使的
String
字符串常量池。 ==
符合使用时,必须保证符合左右两边的变量类型一致,包括 “自动转换”
- 基本数据类型比较判断数值是否相等
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 方法
equals()
是 Object类中的一个方法,所有类都继承了这个方法。所以只有类才可以直接使用,不是类无法使用其方法。- equals() 只适用于引用数据类型,因为 equals() 是 Object 类中的一个方法而已,基本数据类型无法调用 Object 中的方法(包装类可以)
- 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() 和 == 的作用是一样的:比较的是对象的地址,是否指向同一个对象。
- 不过像
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)));
}
}
- 通常情况下,我们自定义的类如果使用equals()的话,重写 equals()方法通常是比较两个对象的 “实体内容” 是否相同,那么我们就需要重写 Object 类中的 equals()方法了。
- 注意不要让左值为 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()方法。
具体操作如下:
- 可以使用快捷键
Alt+Insert
或者鼠标右键,选择Generate...
(该单词是:产生的意思) 这个选项。如果快捷键没有用的话,可能需要配合Fn
功能键一起使用。
- 弹出如下 Generate 窗口,点击
equals() and hashCode()
选项,该选项表示会自动重写 equals() 和 hashCode()方法
- 在再弹出窗口中,选择你所需要的 JDK 版本。这里我们可以选择:java.util.Objects.equals and hashCode(java7+) 这个选项,再 next.
- 重写的 equals() 方法勾选你要比较判断的属性名,如下,点击 next
- 这里是重写 hashCode()方法勾选对应包含的属性名,点击 next
-
所有非空 null 的表示方式,我们也可以勾选上,最后 Finish 就自动生成好了
-
如下就是 IDEA 中帮我们自动重写的 equals() 和 hashCode() 方法
3. == 操作符 与 equals 方法的区别
==
是操作符,不是方法可以直接使用,既可以 比较基本数据类型也可以比较引用数据类型。不过对于基本数据类型比较的是内容值,而对于引用数据类型比较的就是内存的地址了。equals()
是方法需要类调用,它是属于java.lang.Object
类里面的方法,如果该方法没有被重写过,默认也是==
,我们可以看到 String ,Date ,File 包装类等的 equals() 方法是被重写了的,而且 String 类在日常开发中用的比较对多,久而久之,形成了 equals() 是比较值的错误观点 。- 对于 equals() 比较的究竟是地址,还是属性内容值,具体的要看自定义的类有没有重写 Object 的 equals() 方法来判断。
- 通常情况下,重写的 equals() 方法,比较的是类当中相应的属性内容是否相等。
4. toString 方法
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()
}
- 可以根据需要在用户自定义类型中重写 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());
}
}
- 对于我们自定的类,如果没有重写 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自动生成重写的方法。如果不符合条件,再进行一个修改就可以了。
具体操作如下:
- 可以使用快捷键
Alt+Insert
或者鼠标右键,选择Generate...
(该单词是:产生的意思) 这个选项。如果快捷键没有用的话,可能需要配合Fn
功能键一起使用。
- 弹出如下 Generate 窗口,点击
toString()
选项,该选项表示会自动重写 toString()方法
- 弹出如下 Generate toString() 窗口,其中会显示对应类中的所有属性名,可以根据需要使用
Shift / Ctrl
选择你要想打印显示的属性名。最后点击 OK
6. 总结:
==
是操作符可以直接使用,如果是基本数据类型比较的是内容值,如果是引用类型,比较的的地址是否相等,特殊的 String 存在字符串常量池,比较的是内容值equals()
方法, 默认 Object 类中的比较的是地址是否相等,所以一般是需要重写的。- 注意 == 与 equals() 方法的区别
- toString() 方法的使用,重写
7. 最后:
限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,江湖再见,后会有期!!!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82998.html