目录
equals()方法
当需要比较对象是否相等时,往往需要采取重写equals方法和hashcode方法。
用来比较两个引用的虚地址。当且仅当两个引用在物理上是同一个对象时,返回值为true,否则将返回false。
原型:
public boolean equals(Object obj) {
return (this == obj);
}
一般会用来比较两个对象的内容是否相等,因此要重写equals方法,如果不重写的话,比较的内存地址,new出来的两个对象,内存地址是不一样的。
@Override
public boolean equals(Object obj) {
//如果是同一个对象返回true,反之返回false
if (this == obj){
return true;
}
if (obj == null){
return false;
}
//判断类型是否相同
if (this.getClass() != obj.getClass()){
return false;
}
Student student = (Student) obj;
return age == student.age &&
Objects.equals(name, student.name);
}
java对于equals()的要求
自反性
public class Test01 {
public static void main(String[] args) {
Student st1 = new Student();
Student st2 = new Student();
System.out.println(st1.equals(st1));//true
}
}
对称性
public class Test01 {
public static void main(String[] args) {
Student st1 = new Student();
Student st2 = new Student();
System.out.println(st1.equals(st2) == st2.equals(st1));//true
}
}
类推性
public class Test01 {
public static void main(String[] args) {
Student st1 = new Student("张三",18);
Student st2 = new Student("张三",18);
Student st3 = new Student("张三",18);
System.out.println(st1.equals(st2));
System.out.println(st2.equals(st3));
if (st1.equals(st2) && st2.equals(st3)){
System.out.println(st1.equals(st3));//true
}
}
}
一致性
stu1.equals(stu2) == stu1.equals(stu2);
非空性
stu1.equals(null);//false
equals()与 ==
- 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。
- 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。
public class Test01 {
public static void main(String[] args) {
Integer x = new Integer(1);
Integer y = new Integer(1);
System.out.println(x.equals(y));//true
System.out.println(x==y);//false
}
}
hashCode()方法
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。
在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法。
hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。
hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
在散列表中,
1、如果两个对象相等,那么它们的hashCode()值一定要相同;
2、如果两个对象hashCode()相等,它们并不一定相等。
toString()方法
默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示。
public class ToStringExample {
private int number;
public ToStringExample(int number) {
this.number = number;
}
}
public class ToStringExampleTest {
public static void main(String[] args) {
ToStringExample ts = new ToStringExample(100);
System.out.println(ts.toString());
}
}
注意:
toString()方法与类使用要重写该方法,可自定义输出内容
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
toString()方法与数据组使用时,调用Arrays中的toString方法
toString()方法还可以用于对象数组,使用时既要在类中重写toString()方法又要调用Arrays类的toString()方法。
clone()方法
clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。
源码如下:
/*
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
The general intent is that, for any object x, the expression:
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
*/
protected native Object clone() throws CloneNotSupportedException;
其中有一个 native 方法,众所周知 native方法是非java语言实现的方法,仅供程序调用。
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
- 第一次声明保证克隆对象将有单独的内存地址分配。
- 第二次声明表明,原始和克隆的对象应该具有相同的类类型,但它不是强制性的。
- 第三声明表明,原始和克隆的对象应该是平等的equals()方法使用,但它不是强制性的
因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,但是因为该方法是protected,所以都不能在类外进行访问。
要想对一个对象进行复制,就需要对clone方法覆盖。
为什么要进行克隆?
克隆的对象可能包含一些已经修改过得属性,当需要一个型的对象来保存当前“状态“时就得使用clone方法。且clone是一个native方法,运行快。
常见的Object a=new Object();Object b;b=a;这种形式的代码复制的是引用,即对象在内存中的地址,a和b对象仍然指向了同一个对象。
而通过clone方法赋值的对象跟原来的对象同是时独立存在的。
克隆的实现:
浅拷贝(ShallowClone)
一般步骤:
1、被复制的类需要实现Cloneabe接口,该接口为标记接口,不含任何方法。如果不实现的话,调用clone会抛异常(CloneNotSupportedException)
2、覆盖clone方法,访问修饰符改为public,方法中调用super.clone()方法得到需要的复制对象
拷贝对象和原始对象的引用类型引用同一个对象。
在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
通过覆盖Object类的clone()方法可以实现浅克隆。
public class Student implements Cloneable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object clone() {
Student stu = null;
try {
stu = (Student)super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return stu;
}
}
public class CloneTest {
public static void main(String[] args) {
Student student = new Student();
student.setName("小明");
Student stu = (Student)student.clone();
System.out.println(student.getName());//小明
System.out.println(stu.getName());//小明
student.setName("大明");
System.out.println(student.getName());//大明
System.out.println(stu.getName());//小明
}
}
深拷贝(DeepClone)
拷贝对象和原始对象的引用类型引用不同对象。
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。
实现深克隆,可以通过覆盖Object类的clone()方法实现,也可以通过序列化(Serialization)等方式来实现。
public class Address implements Cloneable {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public Object clone() {
Address add = null;
try {
add = (Address)super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return add;
}
}
public class Student implements Cloneable {
private String name;
private Address addr;
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) {
this.addr = addr;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object clone() {
Student stu = null;
try {
stu = (Student)super.clone();//浅复制
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
stu.addr = (Address)addr.clone();//深度复制
return stu;
}
}
public class CloneTest {
public static void main(String[] args) {
Address addr = new Address();
addr.setAddress("北京市");
Student student = new Student();
student.setName("小明");
student.setAddr(addr);
Student stu = (Student)student.clone();
System.out.println(student.getName()+ student.getAddr().getAddress());//小明
System.out.println(stu.getName()+stu.getAddr().getAddress());//小明
addr.setAddress("河北省");
System.out.println(student.getName() +student.getAddr().getAddress());//大明
System.out.println(stu.getName()+stu.getAddr().getAddress());//小明
}
}
本文介绍了Java中Object类的四个重要方法:equals()用于对象内容比较,需要与hashCode()一起重写以满足散列表需求;hashCode()返回对象的哈希码,影响散列表索引;toString()默认返回对象信息,常需重写以定制输出;clone()用于对象复制,分为浅拷贝和深拷贝,实现时需注意接口与权限问题。
16万+

被折叠的 条评论
为什么被折叠?



