关于Object和Objects

关于Object和Objects

第1章 Object类

1.1概述

java.lang.Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。

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

public class MyClass /*extends Object*/ {// ...
}

根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。今天我们主要学习其中的2个:

  • public String toString():返回该对象的字符串表示。
  • public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。

1.2 toString方法

方法摘要

  • public String toString():返回该对象的字符串表示。

toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。

由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。

覆盖重写

如果不希望使用toString方法的默认行为,则可以对它进行覆盖重写。

例如自定义的Person类:

public class Person {  private String name;private int age;@Overridepublic String toString() {return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';}// 省略构造器与Getter Setter
}

在IntelliJ IDEA中,可以点击Code菜单中的Generate...,也可以使用快捷键alt+insert,点击toString()选项。选择需要包含的成员变量并确定。如下图所示:

在这里插入图片描述

小贴士: 在我们直接使用输出语句输出对象名的时候,其实通过该对象调用了其toString()方法。

1.3 equals方法

方法摘要

  • public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。

调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。

默认地址比较

如果没有覆盖重写equals方法,那么Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,结果必然为false。

对象内容比较

如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。例如:

import java.util.Objects;public class Person {	private String name;private int age;@Overridepublic boolean equals(Object o) {// 如果对象地址一样,则认为相同if (this == o)return true;// 如果参数为空,或者类型信息不一样,则认为不同if (o == null || getClass() != o.getClass())return false;// 转换为当前类型Person person = (Person) o;// 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果return age == person.age && Objects.equals(name, person.name);}
}

这段代码充分考虑了对象为空、类型一致等问题,但方法内容并不唯一。大多数IDE都可以自动生成equals方法的代码内容。在IntelliJ IDEA中,可以使用Code菜单中的Generate…选项,也可以使用快捷键alt+insert,并选择equals() and hashCode()进行自动代码生成。如下图所示:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

tips:Object类当中的其他方法,今后学习。

案例:

/** 
* 学生系统中,添加学生信息,并要求同名且同年龄的则为同一人,不允许添加至系统中。 
*  定义一个添加方法,可以将学生添加至容器中。
*/
package com.igeek.javase.code.ch06.object;import java.util.Objects;/*** @Version 1* @Description TODO* @Athuor zhangquan* @Date 2021/9/8 9:45*/
public class Student extends Object {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public Student() {}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;}//重写equals方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age &&Objects.equals(name, student.name);}//重写hashCode方法@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
package com.igeek.javase.code.ch06.object;import java.util.Arrays;
import java.util.Objects;/*** @Version 1* @Description TODO* @Athuor zhangquan* @Date 2021/9/8 13:32*/
public class StudentTest {private Student[] stus=new Student[3];private int index;public Student[] getStus() {return stus;}/*** 添加学生信息到该容器里面,当该容器里面有该学生的信息时(name,age都是一样)就添加失败* @param stu   需要添加的学生对象* @return      添加是否成功的结果*/public boolean add(Student stu){//判断是否需要数组扩容if(index >= stus.length){stus=Arrays.copyOf(stus,stus.length*3/2+1);}//只能存放不同的学生boolean flag=true;for (int i = 0; i < index; i++) {/*if(stus[i] != null){if(stus[i].equals(stu)){flag = false;}}*///等于上面这种写法,Objects 类里面的方法对空指针安全(容忍空指针)if(Objects.equals(stus[i],stu)){flag = false;}}if(flag) {stus[index++]=stu;System.out.println("添加"+stu.getName()+"成功");}return flag;}@Overridepublic String toString() {return "StudentTest{" +"stus=" + Arrays.toString(stus) +", index=" + index +'}';}public static void main(String[] args) {StudentTest ST = new StudentTest();Student stu1 = new Student("张三",18);Student stu2 = new Student("张三",19);Student stu3 = new Student("张三",18);Student stu5 = new Student("李四",18);Student stu6 = new Student("王五",18);Student stu4 = stu1;//添加学生ST.add(stu1);ST.add(stu2);ST.add(stu3);ST.add(stu4);ST.add(stu5);ST.add(stu6);System.out.println(ST.toString());}
}

1.4 clone方法

源码:

@HotSpotIntrinsicCandidateprotected 
native Object clone() throws CloneNotSupportedException;

克隆一个具有该类同样信息的对象,地址不同,属性值相同!

克隆 "拷贝"

  • 若一个类的对象要使用clone(),则当前类必须实现Cloneable接口否则抛出异CloneNotSupportedException

  • Object中clone()是protected权限,只支持本类中调用自身的clone()

  • 若想调用其他类中的clone(),则必须要重写clone(),必须实现Cloneable接口

  • 浅克隆 和 深克隆

案例

public class CloneDemo1 implements Cloneable{//重写方法时,允许将protected权限 --> public权限//可以将返回值由  Object --> CloneDemo1  避免之后使用每次都要强转@Overrideprotected CloneDemo1 clone() throws CloneNotSupportedException {return (CloneDemo1)(super.clone());}
}
public class CloneDemo2 /*extends Object*/ implements Cloneable{public static void main(String[] args) throws CloneNotSupportedException { CloneDemo2 demo1 = new CloneDemo2();//Object.clone()返回的是一个Object类的对象CloneDemo2 demo2 = (CloneDemo2)demo1.clone();System.out.println("demo1 = "+demo1);System.out.println("demo2 = "+demo2);System.out.println("---------------------------");CloneDemo1 demo3 = new CloneDemo1();CloneDemo1 demo4 = demo3.clone();System.out.println("demo3 = "+demo3);System.out.println("demo4 = "+demo4);System.out.println("---------------------------");//Object obj1 = new Object();//Object obj2 = obj1.clone();}
}

浅克隆 和 深克隆

发生在类和类之间有关联关系存在时

浅克隆只克隆外层类,关联类被克隆的是地址

深克隆是将关联类也进行克隆

在这里插入图片描述

在这里插入图片描述

package com.igeek.javase.ch06.object.clone;
public class Person implements Cloneable{private String name;private String gender;private int age;//一对一关联private Phone phone;//重写克隆方法  Ctrl+O@Overrideprotected Person clone() throws CloneNotSupportedException {//浅克隆//Person person = (Person)super.clone();//return person;//深克隆Person person = (Person)super.clone();Phone phone = this.phone.clone();person.setPhone(phone);return person;}public Person() {}public Person(String name, String gender, int age, Phone phone) {this.name = name;this.gender = gender;this.age = age;this.phone = phone;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return gender*/public String getGender() {return gender;}/*** 设置* @param gender*/public void setGender(String gender) {this.gender = gender;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}/*** 获取* @return phone*/public Phone getPhone() {return phone;}/*** 设置* @param phone*/public void setPhone(Phone phone) {this.phone = phone;}public String toString() {return "Person{name = " + name + ", gender = " + gender + ", age = " + age + ", phone = " + phone + "}";}
}
package com.igeek.javase.ch06.object.clone;
public class Phone implements Cloneable {private String label;private double price;//重写克隆方法@Overrideprotected Phone clone() throws CloneNotSupportedException {return (Phone)super.clone();}public Phone() {}public Phone(String label, double price) {this.label = label;this.price = price;}/*** 获取* @return label*/public String getLabel() {return label;}/*** 设置* @param label*/public void setLabel(String label) {this.label = label;}/*** 获取* @return price*/public double getPrice() {return price;}/*** 设置* @param price*/public void setPrice(double price) {this.price = price;}public String toString() {return "Phone{label = " + label + ", price = " + price + "}";}
}
package com.igeek.javase.ch06.object.clone;
public class PersonTest {public static void main(String[] args) throws CloneNotSupportedException {Phone phone = new Phone("华为",6000.0);Person p1 = new Person("张三","男",20, phone);Person p2 = p1.clone();System.out.println("---------------浅克隆----------------");System.out.println("----------克隆后,修改前--------");System.out.println("p1 = "+p1);  //张三  男  20  华为   6000.0System.out.println("p2 = "+p2);  //张三  男  20  华为   6000.0System.out.println("----------克隆后,修改后--------");p1.setGender("女");p1.getPhone().setLabel("苹果");System.out.println("p1 = "+p1);  //张三  女  20  苹果   6000.0System.out.println("p2 = "+p2);  //张三  男  20  苹果   6000.0System.out.println("---------------深克隆----------------");Phone phone2 = new Phone("华为",6000.0);Person p3 = new Person("张三","男",20, phone2);Person p4 = p3.clone();System.out.println("----------克隆后,修改前--------");System.out.println("p3 = "+p3);  //张三  男  20  华为   6000.0System.out.println("p4 = "+p4);  //张三  男  20  华为   6000.0System.out.println("----------克隆后,修改后--------");p3.setGender("女");p3.getPhone().setLabel("苹果");System.out.println("p3 = "+p3);  //张三  女  20  苹果   6000.0System.out.println("p4 = "+p4);  //张三  男  20  华为   6000.0}}

第2章 Objects类

Objects类是对象工具类,它里面的的方法都是用来操作对象的。

2.1 equals方法

在刚才IDEA自动重写equals代码中,使用到了java.util.Objects类,那么这个类是什么呢?

JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象。

在比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问题。方法如下:

  • public static boolean equals(Object a, Object b):判断两个对象是否相等。

我们可以查看一下源码,学习一下:

public static boolean equals(Object a, Object b) {  return (a == b) || (a != null && a.equals(b));  

2.2 isNull

static boolean isNull(Object obj) 判断对象是否为null,如果为null返回true。

Student s1 = null;
Student s2 = new Student("蔡徐坤", 22);// static boolean isNull(Object obj) 判断对象是否为null,如果为null返回true
System.out.println(Objects.isNull(s1)); // true
System.out.println(Objects.isNull(s2)); // false

第3章:补充 equals方法和hashCode方法

源码:

 @HotSpotIntrinsicCandidatepublic native int hashCode();

ps : native关键字是 java 语言和其他语言的交互的信号,即该功能使用了其他语言实现

hashCode()是一种算法,根据hash值将相同hash值得元素划分在一块区域,类似下图的哈希桶,

当两个对象的equals(Object中未被子类重写的)结果相同时,他们的哈希值一定相同,但是hash值相同,equals

不一定相同,可以是一个桶中的不同元素

在开发中我们经常会重写equals()方法,建议这边也重写一下hashCode()方法

具体参考:

(PS:哈希算法是为了提高查查找效率)

在这里插入图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部