当前位置: 首页 > news >正文

根父类 Object 的使用与常用方法(equals\toString\clone\finalize\getClass\hashCode....)

🚀 个人简介:某大型国企资深软件开发工程师,信息系统项目管理师、CSDN优质创作者、阿里云专家博主,华为云云享专家,分享前端后端相关技术与工作常见问题~

💟 作    者:码喽的自我修养🥰
📝 专    栏:Java入门到实战 🎉

🌈 创作不易,如果能帮助到带大家,欢迎 收藏+关注 哦 💕

🌈🌈文章目录 

一、如何理解根父类

二、Object类的方法

1、(重点)equals()

2、(重点)toString()

3、clone()

4、finalize()

5、getClass()

6、hashCode()

一、如何理解根父类

java.lang.Object是类层次结构的根类,即所有其它类的父类。每个类都使用 Object 作为超类。

  • Object类型的变量与除Object以外的任意引用数据类型的对象都存在多态引用
method(Object obj){…} //可以接收任何类作为其参数Person o = new Person();  
method(o);
  • 所有对象(包括数组)都实现这个类的方法。

  • 如果一个类没有特别指定父类,那么默认则继承自Object类。例如:

public class Person {...
}
//等价于:
public class Person extends Object {...
}

二、Object类的方法

根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。这里我们主要关注其中常用的6个:

1、(重点)equals()

= =:

  • 基本类型比较值:只要两个变量的值相等,即为true。

int a=5; 
if(a==6){…}
  • 引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才返回true。
Person p1=new Person();  	    
Person p2=new Person();
if (p1==p2){…}

用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错

equals():所有类都继承了Object,也就获得了equals()方法。还可以重写。

  • 只能比较引用类型,Object类源码中equals()的作用与“==”相同:比较是否指向同一个对象。

  

  • 格式:obj1.equals(obj2)

  • 特例:当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;

    • 原因:在这些类中重写了Object类的equals()方法。

  • 当自定义使用equals()时,可以重写。用于比较两个对象的“内容”是否都相等

  • 重写equals()方法的原则

    • 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。

    • 自反性:x.equals(x)必须返回是“true”。

    • 传递性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。

    • 一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。

    • 任何情况下,x.equals(null),永远返回是“false”;

      ​ x.equals(和x不同类型的对象)永远返回是“false”。

  • 重写举例:

class User{private String host;private String username;private String password;public User(String host, String username, String password) {super();this.host = host;this.username = username;this.password = password;}public User() {super();}public String getHost() {return host;}public void setHost(String host) {this.host = host;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User [host=" + host + ", username=" + username + ", password=" + password + "]";}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;User other = (User) obj;if (host == null) {if (other.host != null)return false;} else if (!host.equals(other.host))return false;if (password == null) {if (other.password != null)return false;} else if (!password.equals(other.password))return false;if (username == null) {if (other.username != null)return false;} else if (!username.equals(other.username))return false;return true;}}

面试题:==和equals的区别

从我近两年作为面试官招聘时的反馈,85%的求职者“理直气壮”的回答错误…

  • == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址

  • equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。

  • 具体要看自定义类里有没有重写Object的equals方法来判断。

  • 通常情况下,重写equals方法,会比较类中的相应属性是否都相等。

练习1:

int it = 65;
float fl = 65.0f;
System.out.println(“65和65.0f是否相等?” + (it == fl)); //char ch1 = 'A'; char ch2 = 12;
System.out.println("65和'A'是否相等?" + (it == ch1));//
System.out.println("12和ch2是否相等?" + (12 == ch2));//String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("str1和str2是否相等?"+ (str1 == str2));//System.out.println("str1是否equals str2?"+(str1.equals(str2)));//System.out.println(“hello” == new java.util.Date()); //

2、(重点)toString()

方法签名:public String toString()

① 默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"

② 在进行String与其它类型数据的连接操作时,自动调用toString()方法

Date now=new Date();
System.out.println(“now=”+now);  //相当于
System.out.println(“now=”+now.toString()); 

③ 如果我们直接System.out.println(对象),默认会自动调用这个对象的toString()

因为Java的引用数据类型的变量中存储的实际上时对象的内存地址,但是Java对程序员隐藏内存地址信息,所以不能直接将内存地址显示出来,所以当你打印对象时,JVM帮你调用了对象的toString()。

④ 可以根据需要在用户自定义类型中重写toString()方法 如String 类重写了toString()方法,返回字符串的值。

s1="hello";
System.out.println(s1);//相当于System.out.println(s1.toString());

 例如自定义的Person类:

public class Person {  private String name;private int age;@Overridepublic String toString() {return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';}
}

3、clone()

//Object类的clone()的使用
public class CloneTest {public static void main(String[] args) {Animal a1 = new Animal("花花");try {Animal a2 = (Animal) a1.clone();System.out.println("原始对象:" + a1);a2.setName("毛毛");System.out.println("clone之后的对象:" + a2);} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}class Animal implements Cloneable{private String name;public Animal() {super();}public Animal(String name) {super();this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Animal [name=" + name + "]";}@Overrideprotected Object clone() throws CloneNotSupportedException {// TODO Auto-generated method stubreturn super.clone();}}

4、finalize()

  • 当对象被回收时,系统自动调用该对象的 finalize() 方法。(不是垃圾回收器调用的,是本类对象调用的)

    • 永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。

  • 什么时候被回收:当某个对象没有任何引用时,JVM就认为这个对象是垃圾对象,就会在之后不确定的时间使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize()方法。

  • 子类可以重写该方法,目的是在对象被清理之前执行必要的清理操作。比如,在方法内断开相关连接资源。

    • 如果重写该方法,让一个新的引用变量重新引用该对象,则会重新激活对象。

  • 在JDK 9中此方法已经被标记为过时的。

public class FinalizeTest {public static void main(String[] args) {Person p = new Person("Peter", 12);System.out.println(p);p = null;//此时对象实体就是垃圾对象,等待被回收。但时间不确定。System.gc();//强制性释放空间}
}class Person{private String name;private int age;public Person(String name, int age) {super();this.name = name;this.age = age;}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;}//子类重写此方法,可在释放对象前进行某些操作@Overrideprotected void finalize() throws Throwable {System.out.println("对象被释放--->" + this);}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}}

5、getClass()

获取对象的运行时类型

因为Java有多态现象,所以一个引用数据类型的变量的编译时类型与运行时类型可能不一致,因此如果需要查看这个变量实际指向的对象的类型,需要用getClass()方法

public static void main(String[] args) {Object obj = new Person();System.out.println(obj.getClass());//运行时类型
}

结果:

class com.atguigu.java.Person

6、hashCode()

public int hashCode():返回每个对象的hash值。(后续文章会重点讲解,欢迎先点个关注~)

public static void main(String[] args) {System.out.println("AA".hashCode());//2080System.out.println("BB".hashCode());//2112
}

到此这篇文章就介绍到这了,更多精彩内容请关注本人以前的文章或继续浏览下面的文章,创作不易,如果能帮助到大家,希望大家点点收藏+关注~💕 

    更多专栏订阅推荐:

🥕 JavaScript深入研究

👍 前端工程搭建
💕 vue从基础到起飞

✈️ HTML5与CSS3

🖼️ JavaScript基础

⭐️ uniapp与微信小程序

📝 前端工作常见问题与避坑指南

✍️ GIS地图与大数据可视化

📚 常用组件库与实用工具

💡 java入门到实战 


http://www.mrgr.cn/news/39539.html

相关文章:

  • 基于SSM的会员管理系统【附源码】
  • LeetCode题练习与总结:有效的字母异位词--242
  • <<迷雾>第5章 从逻辑学到逻辑电路(1)--继电器 示例电路
  • PTVS:Python开发者的Visual Studio扩展
  • Java中的反射性能优化:如何避免反射带来的性能瓶颈
  • Python酷库之旅-第三方库Pandas(131)
  • 【Python报错已解决】TypeError: object of type ‘complex‘ has no len()
  • C#自定义工具类-Transform工具类
  • Linux之进程概念
  • 数据冒险与控制冒险
  • winform—将窗体显示在panel控件中
  • 多处理器的概念与对比
  • Maven(3)什么是POM?
  • Android15车载音频之CarAudioService加载解析各音区参数过程(八十七)
  • Redis缓存穿透雪崩击穿及解决
  • 如何使用 WSL 在 Windows 上安装 Linux
  • WingetUI:可视化Windows常用的命令行包管理工具
  • Vue3 + Vite 开发环境下解决跨域问题:配置代理服务器
  • postgreSql常用操作
  • 【拥抱AIGC】通义灵码网络代理配置