文章目录
第十三章Object祖类
java.lang.Object
类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。
在Object类中有一段描述
Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.
大致意思就是:
类对象是类层次结构的根。每个类都有Object作为超类。所有对象(包括数组)都实现此类的方法。
方法名 | 介绍 |
---|---|
public String toString() | 返回该对象的字符串表示。 |
boolean equals(Object obj) | 指示其他某个对象是否与此对象“相等” |
public native int hashCode() | 对象的内存地址 |
finalize() | 垃圾回收之前执行的代码 |
接下来对Object这个祖类中的方法进行讲解
1.toString方法
1.1方法摘要
方法名 | 介绍 |
---|---|
public String toString() | 返回该对象的字符串表示。我们在输出对象时,默认会调用该对象的toString()方法; |
toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。
举例:
public class ToStringDemo {
public static void main(String[] args) {
Person person=new Person(21,"张三");
System.out.println(person);
}
}
class Person{
private int age;
private String name;
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
输出结果:
toString.Person@4eec7777
包名@内存地址
1.2.2 覆盖重写
如果不希望使用toString方法的默认行为,则可以对它进行覆盖重写。
public class ToStringDemo {
public static void main(String[] args) {
Person person=new Person(21,"张三");
System.out.println(person);
}
}
class Person{
private int age;
private String name;
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
测试结果:
Person{age=21, name='张三'}
重写的规则 自己说了算
上方toString方法就是idea快捷生成的 alt+insert 选择toString即可
2.equals方法
2.1 方法摘要
方法名 | 作用 |
---|---|
public boolean equals(Object obj) | 指示其他某个对象是否与此对象“相等”。 |
调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。
2.2 默认地址比较
如果没有覆盖重写equals方法,那么Object类中默认进行==
运算符的对象地址比较,只要不是同一个对象,结果必然为false。
源码:
public boolean equals(Object obj) {
return (this == obj);
}
我们知道,引用存储的是对象的内存地址。所以这里比较的就是两个引用的内存地址
2.3对象内容比较
public class equalsTest01 {
public static void main(String[] args) {
MyTime m1=new Mytime(2000,2,18);
MyTime m2=new Mytime(2000,2,18);
System.out.println(m1.equals(m2));//true
}
}
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;
}
/*
public boolean equals(Object obj){
//如果obj是空就返回null
if (obj==null){
return false;
}
//如果obj不是Mytime 就返回false
if (!(obj instanceof Mytime)){
return false;
}
//如果obj和this保存的内存地址相等,没必要比较了,直接返回true
//内存相等的情况下,堆内存的对象肯定是同一个
if(this==obj){
return true;
}
//程序到此处说明了什么
//说明obj不是null obj是mmm类型
Mytime t=(Mytime) obj;
if (this.year==t.year &&this.month==t.month&&this.day==t.day){
return true;
}
//程序能到这里返回false
return false;
}
*/
//直接生成的 alt+insert
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Mytime mytime = (Mytime) o;
return year == mytime.year && month == mytime.month && day == mytime.day;
}
@Override
public String toString() {
return "Mytime{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
注意:只要不是基本数据类型我们就要用equals来比较
3.hashCode()方法
代码示例:
/*
hashCode方法:
在Object中的hashCode方法是怎样的?
public native int hashCode();
这个方法不是抽象的,带有native关键字,底层调用c++程序
hashCode()返回的是哈希码
实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值
所以hashCode()方法的执行结果可以等同看作一个java对象的内存地址
*/
public class hashCodeTest {
public static void main(String[] args) {
Object o=new Object();
int hashCodeValue=o.hashCode();
System.out.println(hashCodeValue);
}
}
4.finalize()方法
代码示例:
/*
非重点
关于Object类中的finalize()方法
1.在Object类中的源代码是什么?
protected void finalize() throws Throwable { }
GC来负责调用finalize()方法。
2.finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的
3.这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法。
4.finalize()方法执行的时机
当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法
5.finalize()方法实际上是sun公司为java程序员准备的一个时机,垃圾销毁时机。
如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法中
6.java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间不到,种种条件下
*/
public class finalizeTest01 {
public static void main(String[] args) {
Person p=new Person();
//怎么把person对象变为垃圾
p=null;
//有一段代码是建议垃圾回收器启动
System.gc();//建议启动!!! 不一定启动
}
}
//业务需求:所有对象在JVM中被释放的时候,请记录一下时间
//记录对象被释放的时间点,这个负责记录的代码放在那里?finalize()
class Person{
//重写finalize()方法
//person类型的对象被垃圾回收器回收的时候,垃圾回收器负责调用p.finalize();
protected void finalize() throws Throwable {
System.out.println("即将被销毁");
}
}