案例2:演示equals方法
实现步骤:
- 在测试类(ObjectDemo02)的main方法中,创建两个学生对象,然后比较两个对象是否相同
代码如下所示:
public class ObjectDemo02 { public static void main(String[] args) { // 创建两个学生对象 Student s1 = new Student("itheima" , "14") ; Student s2 = new Student("itheima" , "14") ; // 比较两个对象是否相等 System.out.println(s1 == s2); } }
运行程序进行测试,控制台的输出结果如下所示:
false
因为"=="号比较的是对象的地址值,而我们通过new关键字创建了两个对象,它们的地址值是不相同的。因此比较结果就是false。
我们尝试调用Object类中的equals方法进行比较,代码如下所示:
// 调用equals方法比较两个对象是否相等 boolean result = s1.equals(s2); // 输出结果 System.out.println(result);
运行程序进行测试,控制台的输出结果为:
false
为什么结果还是false呢?我们可以查看一下Object类中equals方法的源码,如下所示:
public boolean equals(Object obj) { // Object类中的equals方法的源码 return (this == obj); }
通过源码我们可以发现默认情况下equals方法比较的也是对象的地址值。比较内存地址值一般情况下是没有意义的,我们希望比较的是对象的属性,如果两个对象的属性相同,我们认为就是同一个对象;
那么要比较对象的属性,我们就需要在Student类中重写Object类中的equals方法。equals方法的重写,我们也可以使用idea开发工具完成,具体的操作如下所示:
- 在空白处使用快捷键:alt + insert。此时会弹出如下的对话框
- 选择equals() and hashCode()方法,此时会弹出如下的对话框
点击next,会弹出如下对话框:
选择neme和age属性点击next,此时就会弹出如下对话框:
取消name和age属性(因为此时选择的是在生成hashCode方法时所涉及到的属性,关于hashCode方法后期再做重点介绍),点击Finish完成生成操作。生成的equals方法和hashCode方法如下:
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return Objects.equals(name, student.name) && Objects.equals(age, student.age); // 比较的是对象的name属性值和age属性值 } @Override public int hashCode() { return 0; }
hashCode方法我们暂时使用不到,可以将hashCode方法删除。重写完毕以后运行程序进行测试,控制台输出结果如下所示:
true
此时equals方法比较的是对象的成员变量值,而s1和s2两个对象的成员变量值都是相同的。因此比较完毕以后的结果就是true。
小结:
- 默认情况下equals方法比较的是对象的地址值
- 比较对象的地址值是没有意义的,因此一般情况下我们都会重写Object类中的equals方法
案例2:对象克隆
把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制
对象克隆的分类:
深克隆和浅克隆
浅克隆:
不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来
基本数据类型拷贝过来的是具体的数据,引用数据类型拷贝过来的是地址值。
Object类默认的是浅克隆
深克隆:
基本数据类型拷贝过来,字符串复用,引用数据类型会重新创建新的
代码实现:
package com.itheima.a04objectdemo; public class ObjectDemo4 { public static void main(String[] args) throws CloneNotSupportedException { // protected object clone(int a) 对象克隆 //1.先创建一个对象 int[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}; User u1 = new User(1, "zhangsan", "1234qwer", "girl11", data); //2.克隆对象 //细节: //方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去。 //书写细节: //1.重写Object中的clone方法 //2.让javabean类实现Cloneable接口 //3.创建原对象并调用clone就可以了 //User u2 =(User)u1.clone(); //验证一件事情:Object中的克隆是浅克隆 //想要进行深克隆,就需要重写clone方法并修改里面的方法体 //int[] arr = u1.getData(); //arr[0] = 100; //System.out.println(u1); //System.out.println(u2); //以后一般会用第三方工具进行克隆 //1.第三方写的代码导入到项目中 //2.编写代码 //Gson gson =new Gson(); //把对象变成一个字符串 //String s=gson.toJson(u1); //再把字符串变回对象就可以了 //User user =gson.fromJson(s, User.class); //int[] arr=u1.getData(); //arr[0] = 100; //打印对象 //System.out.println(user); } } package com.itheima.a04objectdemo; import java.util.StringJoiner; //Cloneable //如果一个接口里面没有抽象方法 //表示当前的接口是一个标记性接口 //现在Cloneable表示一旦实现了,那么当前类的对象就可以被克降 //如果没有实现,当前类的对象就不能克隆 public class User implements Cloneable { private int id; private String username; private String password; private String path; private int[] data; public User() { } public User(int id, String username, String password, String path, int[] data) { this.id = id; this.username = username; this.password = password; this.path = path; this.data = data; } /** * 获取 * * @return id */ public int getId() { return id; } /** * 设置 * * @param id */ public void setId(int id) { this.id = id; } /** * 获取 * * @return username */ public String getUsername() { return username; } /** * 设置 * * @param username */ public void setUsername(String username) { this.username = username; } /** * 获取 * * @return password */ public String getPassword() { return password; } /** * 设置 * * @param password */ public void setPassword(String password) { this.password = password; } /** * 获取 * * @return path */ public String getPath() { return path; } /** * 设置 * * @param path */ public void setPath(String path) { this.path = path; } /** * 获取 * * @return data */ public int[] getData() { return data; } /** * 设置 * * @param data */ public void setData(int[] data) { this.data = data; } public String toString() { return "角色编号为:" + id + ",用户名为:" + username + "密码为:" + password + ", 游戏图片为:" + path + ", 进度:" + arrToString(); } public String arrToString() { StringJoiner sj = new StringJoiner(", ", "[", "]"); for (int i = 0; i < data.length; i++) { sj.add(data[i] + ""); } return sj.toString(); } @Override protected Object clone() throws CloneNotSupportedException { //调用父类中的clone方法 //相当于让Java帮我们克隆一个对象,并把克隆之后的对象返回出去。 //先把被克隆对象中的数组获取出来 int[] data = this.data; //创建新的数组 int[] newData =new int[data.length]; //拷贝数组中的数据 for (int i = 0; i < data.length; i++) { newData[i] = data[i]; } //调用父类中的方法克隆对象 User u=(User)super.clone(); //因为父类中的克隆方法是浅克隆,替换克隆出来对象中的数组地址值 u.data =newData; return u; } }