EffectiveJava-所有对象通用方法

/*
 * 08
 * 覆盖equals时要遵守通用约定
 * 自反性 对称性 传递性 一致性 
 * */
public class Item08 {
	public static void main(String [] arsg){
		Item08 i = new Item08();
		Item08.Student s = i.new Student();
		System.out.println(s.toString());
	}

protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}

class Student{
	String name;
	int id;
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + getOuterType().hashCode();
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (!getOuterType().equals(other.getOuterType()))
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	private Item08 getOuterType() {
		return Item08.this;
	}	

/*	重载
 * public boolean equals(Student obj) {
		return false;
	}*/
}
}


/*
 * 09
 * 覆盖equals时总要覆盖hashcode
 * 如果不着样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作。
 * 
 * 10
 * 要始终覆盖toString方法
 * 当对象被传递给print,printf,字符串联操作符(‘+’),assert或者被调试器打印出来时,toString会自动调用
 * 返回 类名称@散列码的无符号十六进制表示
 * 
 * 11
 * 谨慎覆盖clone
 * 
 * 12
 * 考虑实现Comparable接口
 * 类实现了Comparable接口,就表明它的实例具有内在的排序关系
 * java平台类库中得所有值类(value class)都实现了Comparable接口
 * 
 * 如果一个类的compareTo方法方法施加了一个与equals方法不一致的顺序关系,它任然能够正常工作,
 * 但是,如果一个有序集合(sorted collection)包含了该类的元素,这个集合就可能无法遵守集合接口(Collection,set,map)的通用约定
 * 对于这些接口的通用约定是按照equals方法来定义的,但是有序集合使用了由compareTo方法而不是equals方法所施加的等同性测试
 * 
 * compareTo方法指定了返回值的符号(大于0,小于0,等于0)
 * */
public class Item09 {
	public static void main(String [] argd){
		PhoneNumber pn = new PhoneNumber(123,123,1234);
		System.out.println(pn);//类名@散列码的十六进制表示	lu.PhoneNumber@2a139a55 	lu.PhoneNumber@99bc1(重写hashcode方法)
		Map<PhoneNumber,String> map = new HashMap<PhoneNumber,String>();
		map.put(pn, "jjj");
		System.out.println(map.get(pn));//jjj
		System.out.println(map.get(new PhoneNumber(123,123,1234)));//null	jjj(重写hashcode方法后)
		/*
		 * 解释:由于PhoneNumber方法没有覆盖hashCode方法,从而导致两个相等(equals)的实例具有不同的散列码,
		 * 违反了hashCode的约定,put方法把对象放在一个散列桶中,get方法却从另一个散列桶中查找。即使两个实例正好
		 * 放在同一个散列桶中,get方法也必定会返回null,因为HashMap有一项优化,可以将与每个项相关联的散列码缓存
		 * 起来,如果散列码不匹配,也不必验证对象的等同性。
		 * 
		 * */
	
	}

}

final class PhoneNumber implements Comparable<PhoneNumber>{
	private final short areaCode;
	private final short prefix;
	private final short lineNumber;
	public PhoneNumber(int areaCode,int prefix ,int lineNumber){
		rangeCheck(areaCode ,999, "areaCode");
		rangeCheck(prefix ,999, "prefix");
		rangeCheck(lineNumber ,9999, "line number");
		this.areaCode=(short)areaCode;
		this.prefix=(short)prefix;
		this.lineNumber=(short)lineNumber;
	}
	
	private static void rangeCheck(int arg,int max,String name){
		if(arg < 0 || arg>max)
			throw new IllegalArgumentException(name + ":"+arg);
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(obj==this) return true;
		if(!(obj instanceof PhoneNumber)) return false;
		PhoneNumber pn = (PhoneNumber)obj;
		
		return this.areaCode==pn.areaCode &&
				this.lineNumber==pn.lineNumber &&
				this.prefix==pn.prefix;
	}
	
	/*	重载
	 * public boolean equals(PhoneNumber obj) {
			return false;
		}*/

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return super.toString()+"\n"+areaCode+prefix+lineNumber;
	}
	
	/*
	 * 一个好的散列函数:为不同的对象产生不同的散列码
	 * */
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		int result=17;
		result = 31*result+areaCode;
		result = 31*result+prefix;
		result = 31*result+lineNumber;
		return result;
	}
/*
 * 报错
 * 在未添加泛型时为object
 * 注意此参数与equals方法的区别 equals参数必须为Object
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
*/
	@Override
	public int compareTo(PhoneNumber o) {
		// TODO Auto-generated method stub
		if(areaCode <o.areaCode) return -1;
		if(areaCode >o.areaCode) return 1;
		if(prefix < o.prefix ) return -1;
		if(prefix > o.prefix ) return 1;
		if(lineNumber <o.lineNumber) return -1;
		if(lineNumber > o.lineNumber) return 1;
		return 0;
	}
}

/*
 * 12
 * 考虑实现Comparable接口
 * 类实现了Comparable接口,就表明它的实例具有内在的排序关系
 * java平台类库中得所有值类(value class)都实现了Comparable接口
 * 
 * 如果一个类的compareTo方法方法施加了一个与equals方法不一致的顺序关系,它任然能够正常工作,
 * 但是,如果一个有序集合(sorted collection)包含了该类的元素,这个集合就可能无法遵守集合接口(Collection,set,map)的通用约定
 * 对于这些接口的通用约定是按照equals方法来定义的,但是有序集合使用了由compareTo方法而不是equals方法所施加的等同性测试
 * 
 * compareTo方法指定了返回值的符号(大于0,小于0,等于0)
 * */
public class Item12 {
	public static void main(String [] args){
		Set<String> s = new TreeSet<String>();
		s.add("as");s.add("sd");
		Collections.addAll(s,args);
		System.out.println(s);
		System.out.println(Double.compare(13.123, 13.1230000));
		System.out.println(Float.compare(13.123f, 13.1230001f));//0
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值