一、equals方法
== 是一个比较运算符
equals和==的区别(面试)
1、== :既可以判断基本类型,又可以判断引用类型是否相等
2、== :判断基本类型,判断的是值是否相等
3、== :判断引用类型,判断的是地址是否相等,即判断是否为同一个对象
4、equals 是Object类方法,只能判断引用类型是否相等
5、默认(子类未重写equals方法时)判断的是地址是否相等,子类(Object的子类)中往往重写该方法,用于判断内容是否相等,比如integer\String
//Jdk源码,Object类的equals方法 就是默认比较对象地址是否相同
public boolean equals(Object obj){
return (this == obj);
}
String类的equals方法改写了Object类的equals方法,变成了判断两个值是否相等
//Jdk源码,Object类的 子类String类的equals方法
public boolean equals(Object anObject) {
if (this == anObject) {//如果是同一个对象,则返回true
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;//若两个字符串的每个字符都相等 返回 true
}
}
return false;
}
二、练习
1、重写equals方法
package com.lmdedu.object;
public class EqualsExercise01 {
public static void main(String[] args) {
Person person1 = new Person("lmd",22,'男');
Person person2 = new Person("lmd",22,'男');
System.out.println("未重写equals之前");
//输出f,因为此时还没有重写equals,用的是Object类的equals方法
System.out.println(person1.equals(person2));
System.out.println("重写equals之后");
System.out.println(person1.equals(person2));//输出t
}
}
class Person{
private String name;
private int age;
private char gender;
public Person(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
//重写equals方法
//要求比较两个Person对象的各个属性值 都一样
public boolean equals(Object obj){
//若比较的两个对象为同一个地址则直接返回true
if(this == obj){
return true;
}
//类型判断
if(obj instanceof Person){//是Person类才进行比较
//多态要向下转型后,才能获得子类的特有属性
//进行向下转型,因为需要得到obj的各个属性,
Person p = (Person) obj;
//name为String,为引用数据类型,因为这里只是判断值是否相等,
//而 ==运算符在判断引用数据类型时,判断的是地址是否相等,不能完成题目要求
//String类的equals,在判断时,判断的是内容是否相等,所以采用 equals
//age和gender属于基本数据类型,==在判断基本数据类型时,判断的是值是否相等,所以用==,
//另外 equals也不能判断 基本数据类型
return p.name.equals(this.getName()) && p.age == this.age && p.gender == this.gender;
}
return false;
}
}
2、看看输出真假 
1)判断p1 == p2 ,p1p2为引用数据类型, ==运算符在判断引用数据类型时,判断的是地址,所以为false
2)判断p1.name.equals(p2.name) name为String类,String类的equals方法(重写过)为判断内容是否一样所以true
3)判断p1.equals(p2) p1并未重写equals类,所以用的是Object类的equals方法,判断方法是this == obj,因为p1为引用数据类型,所以判断的是地址,所以false
4)判断s1.equals(s2) s1、s2为String类,String类的equals方法(重写过)为判断内容是否一样所以true
5)判断s1 == s2 ,String类为 引用数据类型,判断 地址,所以false
3、
t t t f t 编译不通过
三、hashcode方法
对象.hashcode();
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable
提供的哈希表)的性能。
由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址(真正的对象地址)转换成一个整数来实现的,但是 Java 编程语言不需要这种实现技巧。)
四、toString方法
package com.lmdedu.object;
public class ToString {
public static void main(String[] args) {
/*
Object的toString源码
1)getClass().getName()类的全类名(包名加类名)
2)Integer.toHexString(hashCode()将对象的hashcode转成16进制的字符串
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*/
Monster monster = new Monster("小妖怪","巡山",1000);
//若没有重写toString,则用Object的toString源码
System.out.println(monster.toString() + "hashcode=" + monster.hashCode());
System.out.println("==当直接输出一个对象时,toString方法会被默认调用==");
System.out.println(monster);//Monster{name='小妖怪', job='巡山', salary=1000.0}
}
}
class Monster{
private String name;
private String job;
private double salary;
public Monster(String name, String job, double salary) {
this.name = name;
this.job = job;
this.salary = salary;
}
//重写toString方法,输出对象的属性
//使用快捷键即可
@Override
public String toString() {//重写后,一般就是将对象的属性输出
return "Monster{" +
"name='" + name + '\'' +
", job='" + job + '\'' +
", salary=" + salary +
'}';
}
}
五、finalize方法(实际开发中,几乎不使用,面试可能问而已)
package com.lmdedu.object;
public class Finalize {
public static void main(String[] args) {
Car bmw = new Car("宝马");
//将bmw与堆中的Car对象的指向 切断,bmw就变成了垃圾,垃圾回收器就会回收(销毁)对象
//在销毁对象前,会调用该对象的finalize方法。
//我们可以重写finalize方法,写自己的一些业务逻辑
//若不重写finalize方法,那么就会调用Object类的finalize方法,即默认处理
bmw = null;
System.gc();//主动调用垃圾回收器
System.out.println("程序退出");
}
}
class Car{
private String name;
public Car(String name) {
this.name = name;
}
//快捷键生成
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("释放了某些资源");
System.out.println("销毁汽车" + name);
}
}