跟随狂神学Java

第十五天:Object类

那日云淡天高,我们正值年少

狂神未更新,转千锋教育 (bilibili.com)

学习内容

Object类的概念

  • 超类、基类,所有类的直接或间接父类,位于继承树的最顶层(也就是所有的类都会直接或间接继承这个类)
  • 任何类,如果没有显式的指明extends继承某个类,都会默认继承Object类,否则为间接继承
  • Object类中所定义的方法,是所有对象都具备的方法
  • Object类型可以储存任何对象
    • 作为参数,可接受任何对象
    • 作为返回值,可返回任何对象
  • 位于java.lang.Object包中

Object类中的一些方法

getClass()方法
  • pubic final Class<?> getClass() {}
  • 返回引用中储存的实际对象类型
  • 应用:通常用于判断两个引用中实际储存对象是否一致
  • 返回值:Class类型

我们来试试

  1. 我们先创建一个类,随便啥的都行

    //这里是Students.javapackage com.joker_yue.javalearn.object;public class Student {private String name;private int age;public Student(){//TODO}public Student(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;}
    }
    
  2. 然后我们创建它的对象

    //这里是TestStudents.javapackage com.joker_yue.javalearn.object;public class TestStudent {public static void main(String[] args) {Student s1 = new Student("aaa",20);Student s2 = new Student("bbb",22);}
    }
  3. 我们来使用getClass()方法,判断二者是否相等

    //这里是TestStudents.javapackage com.joker_yue.javalearn.object;public class TestStudent {public static void main(String[] args) {Student s1 = new Student("aaa",20);Student s2 = new Student("bbb",22);//判断s1和s2是不是同一个类型Class class1 = s1.getClass();         //Class以后讲注解和反射的时候再说嗷Class class2 = s2.getClass();         //那就先鸽这了哈if(class1 == class2){System.out.println("s1与s2是同一个类型");}else{System.out.println("s1与s2不是同一个类型");}}
    }
  4. 最后的运行输出结果为:

    s1与s2是同一个类型
    

hashCode()方法
  • public int hashCode() {}
  • 返回该对象的哈希值(int)
  • 哈希值:根据堆中的对象的地址或字符串或数字使用hash算法来计算出来的int类型的数值
  • 一般情况下, 相同的对象会返回相同的哈希值

我们还是拿之前的例子来举例

//这里是TestStudents.javapackage com.joker_yue.javalearn.object;public class TestStudent {public static void main(String[] args) {//getClass()方法Student s1 = new Student("aaa",20);Student s2 = new Student("bbb",22);//判断s1和s2是不是同一个类型Class class1 = s1.getClass();Class class2 = s2.getClass();if(class1 == class2){System.out.println("s1与s2是同一个类型");}else{System.out.println("s1与s2不是同一个类型");}//hashCode()方法System.out.println(s1.hashCode());System.out.println(s2.hashCode());}
}

​ 最后的输出结果为:

s1与s2是同一个类型
1324119927
990368553

​ 那我们再创建一个s3对象,并使s3=s1;

//这里是TestStudents.javapackage com.joker_yue.javalearn.object;public class TestStudent {public static void main(String[] args) {//getClass()方法Student s1 = new Student("aaa",20);Student s2 = new Student("bbb",22);//判断s1和s2是不是同一个类型Class class1 = s1.getClass();Class class2 = s2.getClass();if(class1 == class2){System.out.println("s1与s2是同一个类型");}else{System.out.println("s1与s2不是同一个类型");}//hashCode()方法System.out.println(s1.hashCode());System.out.println(s2.hashCode());Student s3 = s1;System.out.println(s3.hashCode());}
}

我们会发现s3和s1的hashCode是一样的

s1与s2是同一个类型
1324119927
990368553
1324119927

因为我们是将s1的内存赋值给了s3。在栈中有两个变量s1和s3,但是这两个变量都指向了堆里面的同一个对象


toString()方法
  • public String toString() {}
  • 返回该对象的字符串表示(表现形式)
  • 可以根据项目需求覆盖该方法,如:展示对象各个属性值

我们还是按照上面一样的,尝试toString()方法

//这里是TestStudents.javapackage com.joker_yue.javalearn.object;public class TestStudent {public static void main(String[] args) {//getClass()方法Student s1 = new Student("aaa",20);Student s2 = new Student("bbb",22);//判断s1和s2是不是同一个类型Class class1 = s1.getClass();Class class2 = s2.getClass();if(class1 == class2){System.out.println("s1与s2是同一个类型");}else{System.out.println("s1与s2不是同一个类型");}System.out.println("-----------------");//hashCode()方法System.out.println(s1.hashCode());System.out.println(s2.hashCode());Student s3 = s1;System.out.println(s3.hashCode());System.out.println("-----------------");//toString()方法System.out.println(s1.toString());System.out.println(s2.toString());}
}

最后的输出结果为

s1与s2是同一个类型
-----------------
1324119927
990368553
1324119927
-----------------
com.joker_yue.javalearn.object.Student@4eec7777
com.joker_yue.javalearn.object.Student@3b07d329

我们可以发现它打印的是我们软件包的全名称加上此对象的哈希值(十六进制)

在IDEA中我们可以按住Ctrl+鼠标左键然后点击toString()来查看源码:

我们也可以将toString()进行重写来让其符合我们的需求

//这里是Students.javapackage com.joker_yue.javalearn.object;public class Student {private String name;private int age;public Student(){//TODO}public Student(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;}@Override                                     //【看我看我】public String toString() {return name+":"+age;}
}

然后运行TestStudent.java我们可以得到如下输出:

s1与s2是同一个类型
-----------------
1324119927
990368553
1324119927
-----------------
aaa:20
bbb:22

发现返回的是自己的定义的功能


equals()方法
  • public boolean equals(Object obj) {}
  • 默认实现为(this == obj),比较两个对象是否相同
  • 可进行覆盖,比较两个对象的内容是否相同

先分清楚equals()和==的区别

  • 使用 == 比较
    Java中的8种=基本数据类型(byte,short,char,int,long,float,double,boolean)比较他们之间的值是否相等。
    引用数据类型(类Class引用接口interface引用数组引用),比较的是他们在堆内存地址是否相等。每新new一个引用类型的对象,会重新分配堆内存空间,使用==比较返回false。

  • 使用 equals() 比较
    equals()方法是Object类的一个方法,Java当中所有的类都是继承于Object这个超类。
    JDK1.8 Object类equals方法源码如下,即返回结果取决于两个对象的使用==判断结果。

    public boolean equals(Object obj) {return (this == obj);
    }
    
  • 默认情况下,比较内存地址值是否相等。可以按照需求逻辑,重写对象的equals()方法。

    来自CSDN博主「ConstXiong」的博客

我们来试试

一样的,我们还是这样举例

//这里是TestStudents.javapackage com.joker_yue.javalearn.object;public class TestStudent {public static void main(String[] args) {//getClass()方法Student s1 = new Student("aaa",20);Student s2 = new Student("bbb",22);//判断s1和s2是不是同一个类型Class class1 = s1.getClass();Class class2 = s2.getClass();if(class1 == class2){System.out.println("s1与s2是同一个类型");}else{System.out.println("s1与s2不是同一个类型");}System.out.println("-----------------");//hashCode()方法System.out.println(s1.hashCode());System.out.println(s2.hashCode());Student s3 = s1;System.out.println(s3.hashCode());System.out.println("-----------------");//toString()方法System.out.println(s1.toString());System.out.println(s2.toString());System.out.println("-----------------");//equals()方法System.out.println(s1.equals(s2));System.out.println(s1.equals(s3));}
}

最后的输出结果为:

s1与s2是同一个类型
-----------------
1324119927
990368553
1324119927
-----------------
aaa:20
bbb:22
-----------------
false
true

可以发现 s1.equals(s2) 输出为false,这是因为他们是两个不同的对象

同样的 s1.equals(s3) 输出为ture,原因是因为他们是相同的对象

即使我们重新new一个对象

Student s4 = new Student("aaa",20);

然后将其s4.equals(s1),输出结果也是false。因为我们每new一个对象,就会在堆中重新开辟空间,所以他们(s1,s4)的地址不相同,便会输出false

但是总是有聪明的脑袋们会问,啊~String类不是也有equals()方法嘛,像这样:

String s1 = "我最帅";
String s2 = "我最帅";
System.out.println(s1.equals(s2));

明明就是两个不同的对象为什么会输出ture啊?

这是因为String类重写了equals()方法,让他们比较值而不是比较地址(别混淆了我们现在讲的是Object类!)

这时候又会有聪明的脑袋们问,啊~怎么重写

equals()方法的重写

步骤:

  • 比较两个引用是否指向同一个对象
  • 判断obj是否为null
  • 判断两个引用指向的实际对象类型是否一致
  • 强制类型转换
  • 依次比较各个属性值是否相等
//这里是Students.javapackage com.joker_yue.javalearn.object;public class Student extends Object{                    //【看我看我】//其实extends Object可以不写,因为我们重写了equals()方法了,它会自动隐式的加上extends Objectprivate String name;private int age;public Student(){//TODO}public Student(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;}@Overridepublic String toString() {return name+":"+age;}@Override                                   //⚠️【看我看我】public boolean equals(Object obj) {//1.判断两个对象是否同一个引用if(this==obj) {//判断地址相等return true;}//2.判断obj是否为nullif(obj==null){return false;}//3.判断是否同一个类型
//        if(this.getClass()==obj.getClass()){//
//        }
//这个被废弃if(obj instanceof Student){//instanceof关键字:它的具体作用是测试左边的对象是否是右边类或者该类的子类创建的实例对象,返回值类型为boolean//4.强制类型转换Student s = (Student) obj;if(this.name.equals(s.getName())  && this.age==s.getAge()){return true;}}return false;}
}

finalize()方法
  • 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
  • 垃圾对象:没有有效引用指向此对象时,为垃圾对象
  • 垃圾回收:由GC销毁垃圾对象,释放数据储存空间
  • 自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
  • 手动回收机制:使用System.gc(); 通知JVM执行垃圾回收

​ 我们来试试,让其在垃圾回收的时候自动输出一句话

//这里是Students.javapackage com.joker_yue.javalearn.object;public class Student extends Object{//其实extends Object可以不写,因为我们重写了equals()方法了,它会自动隐式的加上extends Objectprivate String name;private int age;public Student(){//TODO}public Student(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;}@Overridepublic String toString() {return name+":"+age;}@Overridepublic boolean equals(Object obj) {//1.判断两个对象是否同一个引用if(this==obj) {return true;}//2.判断obj是否为nullif(obj==null){return false;}//3.判断是否同一个类型
//        if(this.getClass()==obj.getClass()){//
//        }if(obj instanceof Student){//instanceof关键字:它的具体作用是测试左边的对象是否是右边类或者该类的子类创建的实例对象,返回值为boolean//4.强制类型转换Student s = (Student) obj;if(this.name.equals(s.getName())  && this.age==s.getAge()){return true;}}return false;}@Override                                      //【看我看我】protected void finalize() throws Throwable {System.out.println("对象被回收:"+this.name);}
}

然后我们来创建一个mian方法用来测试重写的finalize()是否成功执行

//这里是TestStudent2.javapackage com.joker_yue.javalearn.object;public class TestStudent2 {public static void main(String[] args) {Student s1 = new Student("aaa",20);Student s2 = new Student("bbb",20);Student s3 = new Student("ccc",20);Student s4 = new Student("ddd",20);Student s5 = new Student("eee",20);//回收垃圾System.gc();System.out.println("回收垃圾");}
}

上述代码的运行结果为

回收垃圾

可以发现我们的重写并没有执行,那我们就换一种写法

//这里是TestStudent2.javapackage com.joker_yue.javalearn.object;public class TestStudent2 {public static void main(String[] args) {//        Student s1 = new Student("aaa",20);
//        Student s2 = new Student("bbb",20);
//        Student s3 = new Student("ccc",20);
//        Student s4 = new Student("ddd",20);
//        Student s5 = new Student("eee",20);new Student("aaa",20);new Student("bbb",20);new Student("ccc",20);new Student("ddd",20);new Student("eee",20);//回收垃圾System.gc();System.out.println("回收垃圾");}
}

上述代码执行后,理应输出如下信息:

aaa对象被回收了
bbb对象被回收了
ccc对象被回收了
ddd对象被回收了
eee对象被回收了
回收垃圾

但是finalize()方法从Java9之后就被弃用了,所以我们可能还是看不到”对象被回收了“

跟随狂神学Java-15相关推荐

  1. 跟着狂神学JAVA的第七天

    八大数据类型 byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间. short:16位,最大数据存储量是65536,数据范围是-32768~32767之间. int:32位, ...

  2. 跟着狂神学SpringCloud(Rest环境搭建+Eureka服务注册与发现+ribbon+Feign负载均衡+Hystrix+服务熔断+Zuul路由网关+SpringCloud config分布)

    跟着狂神学SpringCloud SpringCloud 回顾之前的知识- JavaSE 数据库 前端 Servlet Http Mybatis Spring SpringMVC SpringBoot ...

  3. 跟着狂神学Redis(NoSql+环境配置+五大数据类型+三种特殊类型+Hyperloglog+Bitmap+事务+Jedis+SpringBoot整合+Redis持久化+...)

    跟着狂神学Redis 狂神聊Redis 学习方式:不是为了面试和工作学习!仅仅是为了兴趣!兴趣才是最好的老师! 基本的理论先学习,然后将知识融汇贯通! 狂神的Redis课程安排: nosql 讲解 阿 ...

  4. Java 15 转正了,国内几大互联网公司均有贡献,其中腾讯最为突出!

    25 岁的 Java 2020 年是 Java 诞生的第 25 个年头.在过去的这些年中,Java 在过去增强功能的推动下为用户提供了超过二十年的创新,例如 Java 5 中的泛型,Java 8 中的 ...

  5. IntelliJ IDEA 2020.2 发布:支持Java 15、GitHub审查、运行时异常的排查辅助...

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 局长 来源 | https://www.osc ...

  6. IntelliJ IDEA 2020.2 EAP 5 发布:完美支持Java 15

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 白开水不加糖 来源 | https://www ...

  7. java vue20.2.2浏览器_支持 Java 15!Java 开发工具 IntelliJ IDEA 2020.2发布

    本文主要对IntelliJ IDEA 2020.2新增修复功能进行详细介绍,其中包括对GitHub拉取请求的更高级支持,新的Inspections Widget,还包含许多框架和技术的新功能,包括Ja ...

  8. JDK 15 JAVA 15的新特性展望

    文章目录 JEP 371: Hidden Classes JEP 372: 删除 Nashorn JavaScript Engine JEP 377: 新的垃圾回收器ZGC正式上线了 JEP 378: ...

  9. JAVA 15发布,越来越像C# ?9月排名,C#增幅狠甩JAVA

    2016年.NET Core首个正式版本问世,如今已发布到了.NET Core3.1,再有2个月.NET5也将如约而至,跨平台开发已经快5年.微软 .NET 程序管理总监 Scott 表示,.NET ...

最新文章

  1. iOS微博web网页出现的天坑 (斗鱼App 当前版本5.600有这个bug)
  2. python基础代码库-Python基础数据处理库-NumPy
  3. java基础知识-对象和类
  4. 数论-朴素卢卡斯(Lucas)模板
  5. 动态链接库 仅有.dll文件时候的使用方法
  6. mysql集群从节点无法启动_一次galera cluster集群故障节点无法启动问题排查
  7. 判断一个字符串是否为回文-链队(新建,进队,出队),链栈(新建,进栈,出栈)...
  8. 系统监控Zabbix部署文档
  9. Linux下rz,sz与ssh的配合使用
  10. 使用PHP连接POSTGRES数据库
  11. python房价数据分析波士顿_Python编程数据科学入门 - 波士顿房价数据分析
  12. Web入门-namp的下载与使用
  13. python计算快递运费价格表_python实现快递价格查询系统
  14. safari浏览器关于时间日期格式的兼容问题
  15. MoveIt! RViz Visual Tools设置
  16. ❤️❤️❤️Unity废柴看过来,手把手教你做植物大战僵尸(十四)—— 游戏胜利和失败界面
  17. 中忻嘉业:抖音小店怎样来做
  18. A brief Introduction to Continue Learning / Life long Learning
  19. DZ插件 [1314]模板自由切换 2.0.1版
  20. table标签及排版详解(一)

热门文章

  1. 理特分析发现,韩国处于5G领导者地位
  2. callback (回调)函数讲解
  3. 病毒假冒工行电子银行升级盗取帐号密码(转)
  4. linux bash shell wget 下载google drive(谷歌云端硬盘)中大文件
  5. 安装python时 0x80070003系统找不到指定路径
  6. 【Canvas】HTML5游戏开发的基本流程+P2.js物理引擎实战开发
  7. 电子书 |《阿里巴巴2016双11背后的技术》
  8. iOS从APP中分享出小程序详解
  9. excel没有办法输入汉字和英文字母一输入就报错
  10. GPS从入门到放弃(五) --- GPS导航电文