【367-380】Object类
2022-01-02 00:16:00 # JavaSE

总结

一般类都默认继承 Object 类

toString() 方法

定义类后一般需要重写 toString() 方法

1
2
System.out.println(引用); 
// 这里自动调用引用的 toString 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class _368_Object中的toString方法 {
public static void main(String[] args) {
Object o = new Object();
System.out.println(o.toString());
// 输出 java.lang.Object@1b6d3586

MyTime myTime = new MyTime(2022,1,2);
System.out.println(myTime.toString());
System.out.println(myTime); // 会直接调用myTime的toString方法
// 输出 2022 1 2
}
}

// toString 一般建议重写

/* 返回对象的表示形式
* public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*/

class MyTime{
int year;
int month;
int day;

public MyTime(){}
public MyTime(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}

@Override
public String toString() {
return this.year + " " + this.month + " " + this.day;
}
}

equals() 方法

概述

定义类后一般需要重写 equals() 方法
自带的 equals() 使用双等号,原理是比较内存地址
基本数据类型使用: “ == “
引用数据类型使用: “equals” 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class _370_Object类的equals方法 {
public static void main(String[] args) {
// new Object();
// 判断基本数据类型数据是否相等
// 使用 “==”
int a = 1;
int b = 1;
// true
System.out.println(a == b);

// 判断两个java对象是否相等
// 使用 equals 方法
MyTime1 myTimeA = new MyTime1(2022,1,2);
MyTime1 myTimeB = new MyTime1(2022,1,2);
// "==" 是判断两个对象的"内存地址"是否相等
// 所以是 false
System.out.println(myTimeA == myTimeB);
// 默认 equals() 方法同 "=="
// 所以 equals 需要重写,进而判断类中 "内容" 是否相等
System.out.println(myTimeA.equals(myTimeB));

// 如果是 null
MyTime1 myTimeC = null;
System.out.println(myTimeA.equals(myTimeC));
}
}

/* 判断了两个对象是否相等
public boolean equals(Object obj) {
return (this == obj);
}
*/

class MyTime1{
int year;
int month;
int day;

public MyTime1(){}
public MyTime1(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}

@Override
public String toString() {
return this.year + " " + this.month + " " + this.day;
}

@Override
public boolean equals(Object obj) {
// 空指针 || 无父子关系
if(obj == null || !(obj instanceof MyTime1)) return false;
// 内存地址相同
if(this == obj) return true;
// 内容判断
MyTime1 mt = (MyTime1)obj;
return mt.year == this.year && mt.month == this.month && mt.day == this.day;
}
}

IDEA生成equals()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.util.Objects;

public class _373_IDEA生成equals方法 {
}

class MyTime2{
int year;
int month;
int day;

public MyTime2() {
}

public MyTime2(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}

@Override
public String toString() {
return "MyTime2{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyTime2 myTime2 = (MyTime2) o;
return year == myTime2.year && month == myTime2.month && day == myTime2.day;
}

@Override
public int hashCode() {
return Objects.hash(year, month, day);
}
}

重写Object类的equals方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.util.Objects;

public class _375_重写Object类的equals方法 {
public static void main(String[] args) {
Student s1 = new Student(123, "cc");
Student s2 = new Student(123, "cc");
System.out.println(s1.equals(s2)); // true

Student s3 = new Student(111, new String("cc"));
Student s4 = new Student(111, new String("cc"));
System.out.println(s3.equals(s4)); // true

}
}

class Student{
int id;
String school;

public Student() {}

public Student(int id, String school) {
this.id = id;
this.school = school;
}

@Override
public String toString() {
return "Student{" +
"id=" + id +
", school='" + school + '\'' +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id && Objects.equals(school, student.school);
}

}

重写equals方法要彻底

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import java.util.Objects;

// 总结 重写 equals 方法要彻底
public class _377_equals方法深层次理解 {
public static void main(String[] args) {
User s1 = new User("zhangsan", new Address("北京", "大兴区", "111"));
User s2 = new User("zhangsan", new Address("北京", "大兴区", "111"));
System.out.println(s1.equals(s2));
}
}

class User{
String name;
Address addr;

public User() {
}

public User(String name, Address addr) {
this.name = name;
this.addr = addr;
}

// 重写equals方法
// 规则,用户名和家庭住址都相同
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof User)) return false;
User user = (User) o;
return this.name.equals(user.name)
&& this.addr.equals(user.addr); // 这里由于没有重写Address.equals,所以用的是Object类中的equals方法,双等号比较
}

}

class Address{
String city;
String street;
String zipcode;

public Address() {
}

public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
// 这里没有重写equals方法

}

String类重写了toString和equals

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class _374_String类重写了toStringequals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "ABC";

String str3 = new String("Test1");
String str4 = new String("Test1");
// 比较内存地址 false
System.out.println(str3 == str4);
// String重写了equals方法 true
System.out.println(str3.equals(str4));

// String 重写了 toString 方法
// 如果没重写就是调用 Object 默认的toString,得到类名+"@"+hashcode
System.out.println(str3.toString());
System.out.println(str3);
}
}


finalize() 方法

源代码是:

1
2
protected void finalize() throws Throwable { }

这个方法不需要手动调用,JVM垃圾回收器负责调用,一般finalize()只需要重写;

静态代码块在类加载执行一次,在准备类的时机加载;
finalize()也是时机,是在垃圾回收时机;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class _379_Objectfinalize方法 {
public static void main(String[] args) {
Person person = new Person();
// 如何变成垃圾
person = null;
// 这里没有启动垃圾回收器,原因:垃圾太少,时间没到..

// 于是多造一点...
for (int i = 0; i < 500000; i++) {
Person person1 = new Person();
person1 = null;
}

// 建议垃圾回收器启动
System.gc();

}
}

class Person extends Object{
// java13后这个方法过时了
@Override
protected void finalize() throws Throwable {
System.out.println(this + "即将被销毁");
}
}

hashCode() 方法

源码

1
public native int hashCode();

hashCode() 方法返回的是哈希码:
实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值。所以hashcode ()方法的执行结果可以等同看做一个java对象的内存地址。

1
2
3
4
5
6
7
public class _380_ObjecthashCode方法 {
public static void main(String[] args) {
Object o = new Object();
System.out.println(o.hashCode());
}
}

Prev
2022-01-02 00:16:00 # JavaSE
Next