JAVA——Object
2022/2/20 17:57:12
本文主要是介绍JAVA——Object,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
JDK类库的根类:Object
这个老祖宗类中的方法我们需要先研究一下,因为这些方法都是所有子类通用的。
任何一个类默认继承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.
Since: JDK1.0
See Also: Class
Author: unascribe
Object类当中有哪些常用的方法?
我们去哪里找这些方法呢?
第一种方法:去源代码当中。(但是这种方式比较麻烦,源代码也比较难)
第二种方法:去查阅java的类库的帮助文档。
*什么是API
应用程序编程接口。(Application Program Interface)
整个JDK的类库就是一个javase的API。
每一个API都会配置一套API帮助文档。
SUN公司提前写好的这套类库就是API。(一般每一份API都对应一份API帮助文档。)
目前为止我们只需要知道这几个方法即可:
protected Object clone() // 负责对象克隆的。
int hashCode() // 获取对象哈希值的一个方法。
boolean equals(Object obj) // 判断两个对象是否相等
String toString() // 将对象转换成字符串形式
protected void finalize() // 垃圾回收器负责调用的方法
关于Object中的toString()方法
1、源代码长什么样?
public String toString() {
return this.getClass().getName() + "@" + Integer.toHexString(hashCode());
}
源代码上toString()方法的默认实现是:
类名@对象的内存地址转换为十六进制的形式
2、SUN公司设计toString()方法的目的是什么?
toString()方法的作用是什么?
toString()方法的设计目的是:通过调用这个方法可以将一个“java对象”转换成“字符串表示形式”
3、其实SUN公司开发java语言的时候,建议所有的子类都去重写toString()方法。
toString()方法应该是一个简洁的、详实的、易阅读的.
测试程序:
public class Test01{ public static void main(String[] args){ MyTime t1 = new MyTime(1970, 1, 1); // 一个日期对象转换成字符串形式的话,我可能还是希望能看到具体的日期信息。 String s1 = t1.toString(); //MyTime类重写toString()方法之前 //System.out.println(s1); // MyTime@28a418fc //MyTime类重写toString()方法之后 System.out.println(s1); // 1970年1月1日 //System.out.println(t1.toString()); //1970年1月1日 // 注意:输出引用的时候,会自动调用该引用的toString()方法。 System.out.println(t1); } } 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; } // 重写toString()方法 // 这个toString()方法怎么重写呢? // 越简洁越好,可读性越强越好。 // 向简洁的、详实的、易阅读的方向发展 public String toString(){ //return this.year + "年" + this.month + "月" + this.day + "日"; return this.year + "/" + this.month + "/" + this.day; } }
关于Object类中的equals方法
1、equals方法的源代码
public boolean equals(Object obj) {
return (this == obj);
}
以上这个方法是Object类的默认实现。
2、SUN公司设计equals方法的目的是什么?
以后编程的过程当中,都要通过equals方法来判断两个对象是否相等。
equals方法是判断两个对象是否相等的。
3、我们需要研究一下Object类给的这个默认的equals方法够不够用!!!!
在Object类中的equals方法当中,默认采用的是“==”判断两个java对象
是否相等。而“==”判断的是两个java对象的内存地址,我们应该判断
两个java对象的内容是否相等。所以老祖宗的equals方法不够用,
需要子类重写equals。
4、判断两个java对象是否相等,不能使用“==”,因为“==”比较的是两个
对象的内存地址。
代码验证:
//测试类 public class Test02{ public static void main(String[] args){ // 判断两个基本数据类型的数据是否相等直接使用“==”就行。 int a = 100; int b = 100; // 这个“==”是判断a中保存的100和b中保存的100是否相等。 System.out.println(a == b); //true(相等) false(不相等) // 判断两个java对象是否相等,我们怎么办?能直接使用“==”吗? // 创建一个日期对象是:2008年8月8日。 MyTime t1 = new MyTime(2008, 8, 8); //MyTime t1 = 0x1234; // 创建了一个新的日期对象,但表示的日期也是:2008年8月8日。 MyTime t2 = new MyTime(2008, 8, 8); //MyTime t2 = 0x3698; //测试以下,比较两个对象是否相等,能不能使用“==”??? // 这里的“==”判断的是:t1中保存的对象内存地址和t2中保存的对象内存地址是否相等。 System.out.println(t1 == t2); // false // 重写Object equals方法之前(比较的是对象内存地址) /* boolean flag = t1.equals(t2); System.out.println(flag); //false */ // 重写Object equals方法之后(比较的是内容。) boolean flag = t1.equals(t2); System.out.println(flag); //true // 再创建一个新的日期 MyTime t3 = new MyTime(2008, 8, 9); // 两个日期不相等,就是false。 System.out.println(t1.equals(t3)); // false } }
对应初代equals()方法:
class MyTime { //extends Object{ 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; } // 默认的equals方法 /* public boolean equals(Object obj) { return (this == obj); } */ // 重写Object类的equals方法 // 怎么重写?复制粘贴。相同的返回值类型、相同的方法名、相同的形式参数列表。 // equals到底应该怎么重写?你自己定,你认为两个对象什么相等的时候表示相等,你就怎么重写。 public boolean equals(Object obj) { // 当年相同,月相同,并且日也相同的时候,表示两个日期相同。两个对象相等。 // 获取第一个日期的年月日 int year1 = this.year; int month1 = this.month; int day1 = this.day; // 获取第二个日期的年月日 //int year2 = obj.year; //int month2 = obj.month; //int day2 = obj.day; if(obj instanceof MyTime){ MyTime t = (MyTime)obj; int year2 = t.year; int month2 = t.month; int day2 = t.day; if(year1 == year2 && month1 == month2 && day1 == day2){ return true; } } // 程序能够执行到此处表示日期不相等。 return false; } }
思考:我们这个程序有bug吗?可以运行,但是效率怎么样?低(怎么改造。)
如果出现以下情况,之前的方法运行效率就比较低:
MyTime t4 = null; System.out.println(t1.equals(t4)); //false
改良方法:
public boolean equals(Object obj) { // 如果obj是空,直接返回false if(obj == null){ return false; } // 如果obj不是一个MyTime,没必要比较了 ,直接返回false if(!(obj instanceof MyTime)){ return false; } // 如果this和obj保存的内存地址相同,没必要比较了,直接返回true。 // 内存地址相同的时候指向的堆内存的对象肯定是同一个。 if(this == obj){ return true; } // 程序能够执行到此处说明什么? // 说明obj不是null,obj是MyTime类型。 MyTime t = (MyTime)obj; if(this.year == t.year && this.month == t.month && this.day == t.day){ return true; } // 程序能到这里返回false return false; }
这就比之前的效率要高很多,也对细节处进一步改良:
public boolean equals(Object obj) { if(obj == null || !(obj instanceof MyTime)){ return false; } if(this == obj){ return true; } MyTime t = (MyTime)obj; return this.year == t.year && this.month == t.month && this.day == t.day ; }
这样就更为简介了,时间复杂度和空间复杂度都得到了改良。
(这些方法在IDEA继承开发工具都可以自动帮助编写不用我们手动编写)
IDEA自动编写的equlas()方法程序:
@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; }
探究:java中的字符串String有没有重写toString,equals方法
测试程序:
public class Test03{ public static void main(String[] args){ // 大部分情况下,采用这样的方式创建字符串对象 String s1 = "hello"; String s2 = "abc"; // 实际上String也是一个类。不属于基本数据类型。 // 既然String是一个类,那么一定存在构造方法。 String s3 = new String("Test1"); String s4 = new String("Test1"); // new两次,两个对象内存地址,s3保存的内存地址和s4保存的内存地址不同。 // == 判断的是内存地址。不是内容。 System.out.println(s3 == s4); // false // 比较两个字符串能不能使用双等号? // 不能,必须调用equals方法。 // String类已经重写equals方法了。 System.out.println(s3.equals(s4)); // true // String类有没有重写toString方法呢? String x = new String("HelloWorld"); // 如果String没有重写toString()方法,输出结果:java.lang.String@十六进制的地址 // 经过测试:String类已经重写了toString()方法。 System.out.println(x.toString()); //HelloWorld System.out.println(x); //HelloWorld } }
总结:
1、String类已经重写了equals方法,比较两个字符串不能使用==,必须使用equals。String对象比较的时候必须使用equals方法
equals是通用的。
2、String类已经重写了toString方法。
大结论:
java中什么类型的数据可以使用“==”判断
java中基本数据类型比较是否相等,使用==
java中什么类型的数据需要使用equals判断
java中所有的引用数据类型统一使用equals方法来判断是否相等。
这是规矩。
关于Object类中的finalize()方法(非重点)
1、在Object类中的源代码:
protected void finalize() throws Throwable { }
GC:负责调用finalize()方法。
2、finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的。
3、这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法。
不像equals toString,equals和toString()方法是需要你写代码调用的。
finalize()只需要重写,重写完将来自动会有程序来调用。
4、finalize()方法的执行时机:
当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用
finalize()方法。(类似遗言)
5、finalize()方法实际上是SUN公司为java程序员准备的一个时机,垃圾销毁时机。
如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法当中。
6、静态代码块的作用是什么?
static {
....
}
静态代码块在类加载时刻执行,并且只执行一次。
这是一个SUN准备的类加载时机。
finalize()方法同样也是SUN为程序员准备的一个时机。
这个时机是垃圾回收时机。
7、提示:
java中的垃圾回收器不是轻易启动的,
垃圾太少,或者时间没到,种种条件下,
有可能启动,也有可能不启动。
测试程序:
// 项目开发中有这样的业务需求:所有对象在JVM中被释放的时候,请记录一下释放时间!!! // 记录对象被释放的时间点,这个负责记录的代码写到哪里? // 写到finalize()方法中。 class Person{ // 重写finalize()方法 // Person类型的对象被垃圾回收器回收的时候,垃圾回收器负责调用:p.finalize(); protected void finalize() throws Throwable { // this代表当前对象 System.out.println(this + "即将被销毁!"); } }
public class Test06{ public static void main(String[] args){ for(int i = 0; i < 1000; i++){ Person p = new Person(); p = null; // 有一段代码可以建议垃圾回收器启动。 if(i % 2 == 0){ System.gc(); // 建议启动垃圾回收器。(只是建议,可能不启动,也可能启动。启动的概率高了一些。) } } } }
项目开发中有这样的业务需求:所有对象在JVM中被释放的时候,请记录一下释放时间!!!
记录对象被释放的时间点,这个负责记录的代码写到哪里?
写到finalize()方法中。
关于Object类中的hashCodee()方法
在Object中的hashCode方法是怎样的?
public native int hashCode();
这个方法不是抽象方法,带有native关键字,底层调用C++程序。
hashCode()方法返回的是哈希码:
实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值。
所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址。
测试程序:
public class Test07{ public static void main(String[] args){ Object o = new Object(); int hashCodeValue = o.hashCode(); // 对象内存地址经过哈希算法转换的一个数字。可以等同看做内存地址。 System.out.println(hashCodeValue); //798154996 MyClass mc = new MyClass(); int hashCodeValue2 = mc.hashCode(); System.out.println(hashCodeValue2); //1392838282 MyClass mc2 = new MyClass(); System.out.println(mc2.hashCode()); // 523429237 } } class MyClass { }
总结:
toString()方法
以后所有类的toString()方法是需要重写的。
重写规则,越简单越明了就好。
System.out.println(引用); 这里会自动调用“引用”的toString()方法。
String类是SUN写的,toString方法已经重写了。
equals()方法
以后所有类的equals方法也需要重写,因为Object中的equals方法比较
的是两个对象的内存地址,我们应该比较内容,所以需要重写。
重写规则:自己定,主要看是什么和什么相等时表示两个对象相等。
基本数据类型比较实用:==
对象和对象比较:调用equals方法
String类是SUN编写的,所以String类的equals方法重写了。
以后判断两个字符串是否相等,最好不要使用==,要调用字符串对象的equals方法。
注意:重写equals方法的时候要彻底。
finalize()方法。
这个方法是protected修饰的,在Object类中这个方法的源代码是:
protected void finalize() throws Throwable { }
这篇关于JAVA——Object的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)