Object类常用的方法-clone、finalize、toString、equals、hashcode

本文详细介绍了Java中对象复制的clone方法,如何实现深拷贝,以及equals方法、hashCode方法和toString方法的用途和重写规则。讲解了在比较对象时的注意事项,包括equals和hashCode的关系,并通过实例展示了如何实现对象的正确比较。此外,还探讨了在覆盖equals时为何通常需要同时覆盖hashCode方法,确保散列存储结构中相等对象的哈希码一致。
摘要由CSDN通过智能技术生成
2.4.5 Object类

clone(): “克隆”对象的方法

public class OsExec2{//每个类默认继承Object父类
//调用的OS类clone有异常,需要抛异常
	public static void main(String[] args)throws  CloneNotSupportedException{
		OS win=new OS("windows操作系统");
		OS  linux=win.clone();
		System.out.println(win==linux);//两个对象地址不一样false
		//更改克隆出来的对象名字对被克隆对象没有影响
		linux.name="Linux操作系统";
		System.out.println(win.name);
		System.out.println(linux.name);
}
}
//给类赋予克隆能力,即让类是实现可克隆的接口implements  Cloneable
class OS implements  Cloneable{
	String name;
	public OS(String name){
		this.name=name;
		}
		//覆盖父类Object中clone方法,更改其权限protected->public,具体实现方法直接super.clone()调用
		@Override
	public  OS  clone()throws  CloneNotSupportedException{
		Object obj=super.clone();
		return (OS)obj;//返回类型需要强转为本类类型
		}
}

finalize(): 对象的“遗言”方法(当一个对象要被gc回收的时候,会主动执行的一个方法,主要是释放资源)/gc垃圾回收器

toString(): 制定一个对象打印显示的内容

当我们想要将一个引用数据类型的对象放进打印
语句里面的时候 这个对象会自动的调用toString()
toString()在没有覆盖的时候 和Object类保持一直
Object -> toString() -> 类型@XXX

Student stu=new Student(“zml”,20);
System.out.println(stu);//姓名:zml,年龄:20

@Override
//重写父类的toString方法
public String toString(){
  return "姓名:"+name+",年龄:"+age;
}

例子:球色

public class ExecToString{
public static void main(String[] args){
	Ball b1=new Ball(5);
	Ball  b2=new Ball(2);
	Ball  b3=new Ball(12);
	System.out.println(b1);
	System.out.println(b2);
	System.out.println(b3);
}
}
class Ball{
int number;
public Ball(int number){
this.number=number;}
@Override
public String toString(){
	/*String[] color={"黄","蓝","粉","紫","绿","白","黑","灰","红"};
	for(int i=0;i<color.length;i++){
		if(number==i+1) return number+"号球"+color[i]+"色";
		}
		return "无此球颜色";*/
		String color="黄蓝粉紫绿白黑灰红";
		if(number>=1&&number<=color.length()){
			return number+"号球"+color.charAt(number-1)+"色";
			}
			return  "无此球";
}
}

equals(): 制定一个类型的比较规则

当我们想要将内存里面不同的两个对象 视为相等对象的时侯需要拿着equals作比较
equals方法在没有覆盖的时候 和Object类型保持一致
在Object类里面 equals() -> 比较地址

如果不想要比较地址的话 需要覆盖equals()
@Override
public boolean equals(Object obj){
if(obj == null)return false;
if(!(obj instanceof 当前类型))return false;
if(obj == this)return true;

​ 制定比较规则

}

基本数据类型==比较;引用数据类型equals比较

public class EqualsExec{
public  static  void main(String[] args){
	Student s1=new Student("小明");
	Student s2=new Student("小红");
  System.out.println(s1==s2);//连等号比地址
	System.out.println(s1.equals(s2));//equals比内容
}}
class Student{
	String name;
	public Student(String name){
		this.name=name;
		}

	@Override
	public boolean equals(Object obj){//覆盖父类的equals方法
		return this.name.equals(((Student)obj).name);
	//	Student x=this;
	//  Student y=(Student)obj;
	//	return x.name.equals(y.name);
		}
	}

equals健壮的写法

​ if(obj==null) return false;//排除空指针异常

​ if(!(obj instanceof Student)) return false;//判断obj是否属于Student类

​ if(obj==this) return true;//obj与当前调用equals对象this相等的话直接返回true,让代码高效运行

public class EqualsExec3{
public  static  void main(String[] args){
    Cat  cc=new Cat("小猫咪");
	Student s1=new Student("小明");
	Student s2=new Student("小红");
	System.out.println(s1.equals(s2));
	System.out.println(s1.equals(cc));
	System.out.println(cc.equals(cc));
}}
class  Cat {
	String name;
	public Cat(String name){
		this.name=name;
		}
	}
class Student{
	String name;
	public Student(String name){
		this.name=name;
		}

	@Override
	public boolean equals(Object obj){
   		//由于参数是Object类型 导致所有的引用数据类型都可以传递进来
		//所有的引用数据类型默认值都是null 为了防止出现空指针异常
		//所以进行排空判断  如果参数是null 那么直接返回false
		//保证代码的健壮性
		if(obj==null) return false;
		//由于参数是Object类型 所以导致所有的引用数据类型都可以传递进来
		//但是学生类的equals方法应该和学生做比较
		//所以只要参数不是学生类型的话 统一返回false
		//保证代码的健壮性
		if(!(obj instanceof  Student)) return false;
		//保证代码高效
		if(obj==this) return true;
		return this.name.equals(((Student)obj).name);
	//	Student x=this;
	//  Student y=(Student)obj;
	//	return x.name.equals(y.name);
		}
	}

面试题: ==与equals区别?

不同点==equals
含义运算符Object类里面一个方法
比较如果比较基本数据类型 比较数值是否一样
如果比较引用数据类型 比较地址是否一样
程序员可以按照自己的意愿 将内存里面
不同的两个对象视为相等对象【逻辑相等】
比如:String类型 Sun公司通过覆盖equals()
让两个字符串只要内容一样就视为相等对象

hashCode(): 用于返回字符串的哈希码

hashcode代表对象的地址说的是对象在hash表中的位置,物理地址说的对象存放在内存中的地址

例:hash表中有 hashcode为1、hashcode为2、(…)3、4、5、6、7、8这样八个位置,有一个对象A,A的物理地址转换为一个整数17(这是假如),就通过直接取余算法,17%8=1,那么A的hashcode就为1,且A就在hash表中1的位置。

作用:

HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的(后半句说的用hashcode来代表对象就是在hash表中的位置)

hashcode和equals的关系

1、如果两个对象equals相等,那么这两个对象的HashCode一定也相同

2、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置

public class TestHashcode {
  public static void main(String args[]) {
    String Str = new String("www.Oracle.com");
      System.out.println("字符串的哈希码为 :" + Str.hashCode() );//字符串的哈希码为 :706482664
        }
}

为什么equals方法重写的话,建议也一起重写hashcode方法?

比如:有个A类重写了equals方法,但是没有重写hashCode方法,看输出结果,对象a1和对象a2使用equals方法相等,按照上面的hashcode的用法,那么他们两个的hashcode肯定相等,但是这里由于没重写hashcode方法,他们两个hashcode并不一样,所以,我们在重写了equals方法后,尽量也重写了hashcode方法,通过一定的算法,使他们在equals相等时,也会有相同的hashcode值。
注意:当此方法[equals]被重写时,通常有必要重写 hashCode 方法,
以维护 hashCode 方法的常规协定,
该协定声明相等对象必须具有相等的哈希码。

x.equals(y) == true

x.hashCode() == y.hashCode()
public class TestStrinBuffer{
public static void main(String[] args){
	Computer lenovo=new Computer("联想",14.0,'灰',6099,false);
	Computer lenovo2=new Computer("联想",14.0,'灰',6099,true);
	System.out.println(lenovo);
	System.out.println(lenovo2);
	System.out.println(lenovo.equals(lenovo2));
	System.out.println(lenovo.hashCode());

}
}
class Computer{
String name;
double size;
char color;
int price;
boolean isShangshi;
public Computer(String name,double size,char color,int price, boolean isShangshi){
	this.name=name;
	this.size=size;
	this.color=color;
	this.price=price;
	this.isShangshi=isShangshi;
}
@Override
public boolean equals(Object obj){
	if(obj==null||!(obj instanceof Computer))  return false;
	if(obj==this) return true;
	return this.name.equals(((Computer)obj).name)&&this.size==((Computer)obj).size&&this.color==((Computer)obj).color&&this.price==((Computer)obj).price&this.isShangshi==((Computer)obj).isShangshi;
	}
	@Override
	public int hashCode(){
		return  name.hashCode()+(int)size*10+color+price+(isShangshi? 1:0);
		}
	@Override
	public String  toString(){
		StringBuffer buffer=new StringBuffer();
					buffer.append(name);
					buffer.append("的电脑新出来是一款");
					buffer.append(color);
					buffer.append("颜色,尺寸是");
					buffer.append(size);
					buffer.append(",售价是:");
					buffer.append(price);
					buffer.append(isShangshi ?  "已经上市" : "至今还没有上市");
					return String.valueOf(buffer);//valueOf()输出String中buffer的值
					//return buffer.toString();//buffer再次调用toString()方法返回字符串
		}
}
public class TestHashCode1{
	public static void main(String[] args){

		String x = new String("OK");//79 * 31(1) + 75  =
		String y = new String("OK");

		System.out.println(x == y);//地址:false
		System.out.println(x.equals(y));//内容:true
		//String extends Object => hashCode()
		System.out.println(x.hashCode());
		System.out.println(y.hashCode());

		Student s1 = new Student("张三");
		Student s2 = new Student("张三");
		System.out.println(s1 == s2);//地址:false
		System.out.println(s1.equals(s2));//true
		System.out.println(s1.hashCode());
		System.out.println(s2.hashCode());//'张' * 31 + '三'

	}
}

class Student{//extends Object => hashCode()

	String name;

	public Student(String name){
		this.name = name;
	}

	@Override
	public boolean equals(Object obj){
		//if if if
		return this.name.equals(((Student)obj).name);
	}

	@Override
	public int hashCode(){
		return name.hashCode();
	}
}
/**
							Object
							toString():打印对象 -》 类型@XXX
							equals():比较对象 -》地址
							hashCode():生成哈希码值 -》 通过地址

		String										Student
		继承得到:									继承得到:
		toString():String@XXX						toString():Student@XX
		equals():地址								equals():地址
		hashCode():地址								hashCode():地址

		方法覆盖:									方法覆盖:
		toString():内容
		equals():内容								equals():name
		hashCode():内容
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值