JAVA基础(二)--------三大特性之--继承(下)Object及对于所有对象都通用的方法

      说到继承,不得不提到的是所有对象的共同父类:Object

      尽管Object是一个具体类,但设计它主要是为了扩展。

      一:相等测试equals

      查看Object的源代码我们可以知道,Object的equals比较的就是两个具体对象是否有相同的引用

     因此当我们不需要考虑类是否逻辑相等,或者超类覆盖的equals子类适用,那么我们都不需要覆盖Object的equals方法。

     而当我们需要考虑类的逻辑相等,也就是一个类中的属性域比较时,我们需要覆盖,但如果不注意会有很多错误发生,下面举例说明:

    

class Human{
	private int age;
	
	public Human(int age) {
		this.age = age;
	}
	
	@Override
	public boolean equals(Object obj){
		if (obj == this) {
			return true;
		}
		
		if (obj == null) {
			return false;
		}
		
		if (!(obj instanceof Human)) {
			return false;
		}
		
		return this.age == ((Human)obj).age;
	}
}

public class Main {
	public static void main(String[] args) {
		HashMap<Human, String> map = new HashMap<Human, String>();
		map.put(new Human(15), "nice");
		String s = map.get(new Human(15));
		System.out.println(s);
	}
}
>>>out:null

我们期望map.get(new Human(15))会返回"nice",但实际上却返回了null。这是为什么呢?

因为我们没有覆盖hashCode()方法

1.如果两个对象相等那么它们必须有相同的hashCode

2.如果两个对象的hashCode相同,它们不一定相等

一般来说我们可以用Eclipse自带的hashCode生成器生成如下方法

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		return result;
	}

若在企业级应用中可以使用第三方库Apache commons HashcodeBuilder


同时在设计equals方法的时候注意满足以下关系:

对于任何非null的x,y,z

*自反性 x.equals(x) 必须返回 true

*对称性 当 y.equals(x) 为true时   x.equals(y) 为true

*传递性 当 x.equals(y) 为true 且  y.equals(z) 为 true      那么 x.equals(z)为true

*一致性 只要x和y没有被修改 那么 x.equals(y) 不管调用多少次 都一直返回true一直返回false


      二:toString方法 及 clone方法

       Object提供了一个toString的实现,但只是返回类名@hashCode,我们无法通过这个toString得到更多的信息,因此一般会约定所有的子类都覆盖这一个方法,以便我们得到更详细的关于这个类所创建的对象的信息。

       为什么我们需要clone,clone又什么用呢?

      在编程中我们经常会遇到这样的情况:某A对象是可变的,当A初始化成功并赋值,这时我们需要一个以A为模板和A完全一样的B,如果我们直接B=A那么当A改变的时候,B也会随之改变,这时我们希望有一个可以完全拷贝A对象的内容的方法,这就是clone方法(当然我们还可以有其它的办法,如类的序列化,这个就不是本章涉及的内容了)


       关于clone我们有浅拷贝和深拷贝之分,下面举例说明:

class Human implements Cloneable{
	private String name;
	private Leg leg;
	
	public Human(String name, Leg leg){
		this.name = name;
		this.leg = leg;
	}
	
	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public Leg getLeg() {
		return leg;
	}


	public void setLeg(Leg leg) {
		this.leg = leg;
	}

	@Override
	public String toString(){
		return "Human: name= " + this.name + ";his leg = " + this.leg;
	}
	
	@Override
	public Human clone() throws CloneNotSupportedException{
		return (Human)super.clone();
	}
}

class Leg{
	private int length;
	
	public Leg(int length){
		this.length = length;
	}
	
	public void setLength(int length) {
		this.length = length;
	}

	public int getLength(){
		return this.length;
	}
	
	public String toString(){
		return "Leg: length= " + this.length;
	}
}

public class Demo {

	public static void main(String[] args) throws CloneNotSupportedException {
		Leg leg = new Leg(10);
		Human human = new Human("xiaoming", leg);
		Human human2 = human.clone();
		human.setName("lilei");
		leg.setLength(15);
		System.out.println("human: " + human);
		System.out.println("human2: " + human2);

	}

}
>>>out:
human: Human: name= lilei;his leg = Leg: length= 15
human2: Human: name= xiaoming;his leg = Leg: length= 15

我们可以看到浅拷贝时,当对象的域为数值或基本类型的时候没有问题,改变A但B不会改变,但当域为可变类型的时候,像Leg改变后A和B都跟着改变了其中的值,为了实现深拷贝,必须克隆所有可变的实例域

class Human implements Cloneable{
	private String name;
	private Leg leg;
	
	public Human(String name, Leg leg){
		this.name = name;
		this.leg = leg;
	}
	
	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public Leg getLeg() {
		return leg;
	}


	public void setLeg(Leg leg) {
		this.leg = leg;
	}

	@Override
	public String toString(){
		return "Human: name= " + this.name + ";his leg = " + this.leg;
	}
	
	@Override
	public Human clone() throws CloneNotSupportedException{
		Human human = (Human)super.clone();
		human.leg = (Leg) leg.clone();
		return human;
	}
}

class Leg implements Cloneable{
	private int length;
	
	public Leg(int length){
		this.length = length;
	}
	
	public void setLength(int length) {
		this.length = length;
	}

	public int getLength(){
		return this.length;
	}
	
	public String toString(){
		return "Leg: length= " + this.length;
	}
	
	public Leg clone() throws CloneNotSupportedException{
		return (Leg) super.clone();
	}
}

public class Demo {

	public static void main(String[] args) throws CloneNotSupportedException {
		Leg leg = new Leg(10);
		Human human = new Human("xiaoming", leg);
		Human human2 = human.clone();
		human.setName("lilei");
		leg.setLength(15);
		System.out.println("human: " + human);
		System.out.println("human2: " + human2);

	}

}
>>>out:
human: Human: name= lilei;his leg = Leg: length= 15
human2: Human: name= xiaoming;his leg = Leg: length= 10



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值