Object类的学习
**引言:**Object类作为所有类的超类,有一些方法是值得研究的。因为这些方法是所有子类都继承了的。(任何一个子类,都会直接或间接继承Object类)
此外,有两种方法查看常用类的常用方法:
- 查看Sun公司写的源码
- 通过API帮助文档
什么是API?Application Program Interface
应用程序编程接口
整个JDK的类库就是一个Java SE的API。
每一个API都会配置一套API帮助文档
1. Object类中有哪些常用方法?
- protected Object clone(){}// 负责对象克隆的
- int hashCode(){}//获取对象哈希值的一个方法
- boolean equals(Object obj){}//判断两个对象是否相等
- String toString(){}//将对象转换成字符串形式
- protected void finalize(){}// 垃圾回收器负责调用的方法
1).toString() 方法
1. toString源代码长什么样
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
2. toString 方法的作用
toString()方法的设计目的是:通过调用这个方法可以将一个“Java对象”转换成“字符串表示形式”。
3.重写 toString方法
public class Test01{
public static void main(String[] args){
MyTime m = new MyTime(2021,4,21);
//重写toString方法之前
//System.out.println(m);//MyTime@4517d9a3
//实际上我不想显示对象的地址,我想显示具体的内容
//那么考虑重写MyTime类的toString方法
System.out.println(m);//2021年4月21日
//输出引用会自动调用toString方法(m.toString)
}
}
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方法
public String toString(){
return this.year+"年"+this.month+"月"+this.day+"日";
}
}
2).equals方法
1.源码长啥样?
//显然,判断时用的是 == ,无法比较两个对象的实际内容是否一致,只能比较两个引用的地址是否一致。
public boolean equals(Object obj) {
return (this == obj);
}
2. equals的作用?
以后编程的过程当中,都要通过equals方法来判断两个对象是否相等。
equals方法是判断两个对象是否相等的。
public class Test02{
public static void main(String[] args){
int i = 100;
int j = 100;
System.out.println(i == j);//true
MyTime m1 = new MyTime(2021,4,21);//m1:0x1111
MyTime m2 = new MyTime(2021,4,21);//m2:0x2222
System.out.println(m1 == m2);//false,
//这里只是比较了两个引用存放的对象的地址,显然是不同的
//调用重写之前的equals方法
//System.out.println(m1.equals(m2));//false,
//从源码看出继承的equals方法仍然使用 == 判断
//要比较对象的内容,只能考虑重写equals方法
System.out.println(m1.equals(m2));//true
m2 = null;
System.out.println(m1.equals(m2));//false
MyTime m3 = new MyTime(2021,4,22);
System.out.println(m1.equals(m3));//false
}
}
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) {
//保存第一个对象的年月日
int year1 = this.year;
int month1 = this.month;
int day1 = this.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;
}
*/
public boolean equals(Object obj){
//如果obj为空,或者不是同一类型的对象,直接返回flase
if(obj == null || !(obj instanceof MyTime))
return false;
if(obj == this)
return true;//说明是同一个对象
MyTime t = (MyTime)obj;//向下转型是多态机制的体现,即obj指向的对象可以是Mytime类型的,但是编译过程中obj是Object类型的,显然Object类型中并没有year,month,day这三个属性,所以进行向下转型。
return t.year == this.year && t.month == this.month && t.day == this.day;
}
}
2. String类是否重写了toString和equals方法?
重写了
/*
java语言当中的字符串String有没有重写toString方法,有没有重写equals方法。
总结:
1、String类已经重写了equals方法,比较两个字符串不能使用==,必须使用equals。
equals是通用的。
2、String类已经重写了toString方法。
大结论:
java中什么类型的数据可以使用“==”判断
java中基本数据类型比较是否相等,使用==
java中什么类型的数据需要使用equals判断
java中所有的引用数据类型统一使用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("动力节点");
// 如果String没有重写toString()方法,输出结果:java.lang.String@十六进制的地址
// 经过测试:String类已经重写了toString()方法。
System.out.println(x.toString()); //动力节点
System.out.println(x); //动力节点
}
}
练习
字符串比较只能使用equals方法,正好String类中重写了equals方法!!!
public class Test01 {
public static void main(String[] args) {
Student s1 = new Student(10,"张三");
Student s2 = new Student(10,"张三");
System.out.println(s1.equals(s2));
}
}
class Student{
int no;
String name;
public Student() {
}
public Student(int no, String name) {
this.no = no;
this.name = name;
}
//重写toString方法
@Override
public String toString() {
return "学号:"+this.no+", 姓名:"+this.name;
}
//重写equals方法
@Override
public boolean equals(Object obj) {//多态
if(obj == null || !(obj instanceof Student))
return false;
if(obj == this)
return true;
Student s =(Student)obj;
return s.no == this.no && this.name.equals(s.name);//这里的qequals调用的是字符串String类的equals方法
}
}
注意:
equals方法的调用层层嵌套,所以equals方法的重写要彻底
public class Test04{//euqals方法会层层嵌套,所以equals方法重写要彻底
public static void main(String[] args){
User u1 = new User("张三",new Address("北京","朝阳区","1111"));
User u2 = new User("张三",new Address("北京","朝阳区","1111"));
System.out.println(u1.equals(u2));
}
}
class User{
String name;
Address addr;
public User(String name,Address addr){
this.name = name;
this.addr = addr;
}
public boolean equals(Object obj){
if(obj == null || !(obj instanceof User))
return false;
if(this == obj) return true;
//转换
User u = (User)obj;
return this.name.equals(u.name) && this.addr.equals(u.addr);//会继续调用引用类型属性的equals方法
}
}
class Address{
String city;
String street;
String zipcode;
public Address(String city,String street,String zipcode){
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
public boolean equals(Object obj){
if(obj == null || !(obj instanceof Address))
return false;
if(this == obj)
return true;
//转换
Address a =(Address)obj;
return this.city.equals(a.city) && this.street.equals(a.street) && this.zipcode.equals(a.zipcode);//继续调用String类型的equals方法
}
}
3. Object类中有哪些常用方法(2)?
1). finalize 方法
- 源码(已经过时了)
本方法只有空方法体,没有代码。并且该方法由protected修饰!
protected void finalize() throws Throwable { }
- finalize方法的使用
本方法不需要手动调用,是Sun公司提供的一个垃圾回收时机,JVM的垃圾回收器负责调用该方法,如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法当中。
- finalize 方法的执行时机:
当一个对象被垃圾回收器回收的时候,垃圾回收器负责调用finalize方法
- 提示:
Java中的垃圾回收器不是轻易启动的,
垃圾太少,或者时间没到,种种条件下,
有可能启动,也有可能不启动。
2). int hashCode() 方法
- 源码
这个方法不是抽象方法,带有native关键字,底层调用C++程序。
public native int hashCode();
- hashCode()方法返回的是哈希码:
实际上就是一个Java对象的内存地址,经过哈希算法,得出的一个值。
所以hashCode()方法的执行结果可以等同看做一个Java对象的内存地址。
public class Test05{
public static void main(String[] args){
Object o = new Object();
System.out.println(o.hashCode());//617901222
}
}