- package codeTemplate.effectiveJava.bean;
-
- public class PhoneNumber {
- private short areaCode, prefix, lineNum;
-
- @Override
- public boolean equals(Object obj) {
- //使用==操作符检查“参数是否为这个对象的引用”
- if (obj == this) {
- return true;
- }
- //使用instanceof操作符检查“参数是否为正确的类型”
- if (!(obj instanceof PhoneNumber)) {
- return false;
- }
- //把参数转化为正确的类型
- PhoneNumber phoneNumber = (PhoneNumber) obj;
- //对于该类中的每一个关键域,检查参数中的域是否与该对象中对应的域相匹配
- return phoneNumber.areaCode == this.areaCode && phoneNumber.prefix == this.prefix && phoneNumber.lineNum == this.lineNum;
- //编写完equals方法后,问自己:他是否是对称的,传递的,一致的
- }
- }
- @Override
- public int hashCode() {
- //Object类有一个静态方法,它带有任意数量的对象,并为他们返回一个散列码
- return Objects.hash(areaCode, prefix, lineNum);
- }
IDE自动生成的方法
- package codeTemplate.effectiveJava.bean;
-
- import java.util.Objects;
-
- public class PhoneNumber {
- private short areaCode, prefix, lineNum;
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- PhoneNumber that = (PhoneNumber) o;
-
- if (areaCode != that.areaCode) return false;
- if (prefix != that.prefix) return false;
- return lineNum == that.lineNum;
- }
-
- @Override
- public int hashCode() {
- int result = areaCode;
- result = 31 * result + (int) prefix;
- result = 31 * result + (int) lineNum;
- return result;
- }
- }
使用IDE自动生成,可自己做调整
- @Override
- public String toString() {
- return "PhoneNumber{" +
- "areaCode=" + areaCode +
- ", prefix=" + prefix +
- ", lineNum=" + lineNum +
- '}';
- }
clone方法就是另一个构造器,必须确保它不会伤害到原始的对象,并确保正确地创建被克隆对象中的约束条
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
默认方法,只会克隆基本类型的值,应用类型的引用,自己实现时需要修正任何需要修正的域
- package codeTemplate.effectiveJava.bean;
-
- import java.util.Objects;
-
- public class PhoneNumber {
- private short areaCode, prefix, lineNum;
- private PhoneArea phoneArea;
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- PhoneNumber clone = (PhoneNumber) super.clone();
- clone.phoneArea = this.phoneArea;
- return phoneArea;
- }
- }
对象拷贝的更好的方法是提供一个拷贝构造器或拷贝工厂
- public class PhoneNumber {
- private short areaCode, prefix, lineNum;
- private PhoneArea phoneArea;
-
- PhoneNumber(PhoneNumber phoneNumber) {
- this.areaCode= phoneNumber.areaCode;
- this.prefix= phoneNumber.prefix;
- this.lineNum= phoneNumber.lineNum;
- this.phoneArea= phoneNumber.phoneArea;
- }
- }
- PhoneNumber(PhoneNumber phoneNumber) {
- this.areaCode= phoneNumber.areaCode;
- this.prefix= phoneNumber.prefix;
- this.lineNum= phoneNumber.lineNum;
- this.phoneArea = new PhoneArea(phoneNumber.phoneArea.getCountry());
- }
- package codeTemplate.effectiveJava.bean;
-
- import lombok.Getter;
- import lombok.Setter;
-
- @Setter
- @Getter
- public class PhoneArea {
- private String Country;
-
- public PhoneArea(String country) {
- Country = country;
- }
- }
拷贝构造方法相比于clone方法的优势:
方法一:
- package codeTemplate.effectiveJava.bean;
-
- import java.util.Objects;
-
- public class PhoneNumber {
- private short areaCode, prefix, lineNum;
- private PhoneArea phoneArea;
-
- public PhoneNumber(PhoneNumber phoneNumber) {
- this.areaCode= phoneNumber.areaCode;
- this.prefix= phoneNumber.prefix;
- this.lineNum= phoneNumber.lineNum;
- this.phoneArea = new PhoneArea(phoneNumber.phoneArea.getCountry());
- }
-
- public static PhoneNumber newInstance(PhoneNumber phoneNumber) {
- return new PhoneNumber(phoneNumber);
- }
- }
方法二:
- package codeTemplate.effectiveJava.bean;
-
- import java.util.Objects;
-
- public class PhoneNumber {
- private short areaCode, prefix, lineNum;
- private PhoneArea phoneArea;
-
- public PhoneNumber() {
- }
-
- public static PhoneNumber newInstance(PhoneNumber phoneNumber) {
- PhoneNumber pn = new PhoneNumber();
- pn.areaCode= phoneNumber.areaCode;
- pn.prefix= phoneNumber.prefix;
- pn.lineNum= phoneNumber.lineNum;
- pn.phoneArea = new PhoneArea(phoneNumber.phoneArea.getCountry());
- return pn;
- }
- }
每当实现一个对排序敏感的类时,都应该让这个类实现Comparable接口,以便其实例可以轻松地被分类、搜索、以及用在基于比较的集合中。每当在compareTo方法的实现中比较域值时,都要避免使用<和>操作符,而应该在装箱基本类型的类中使用静态的compare方法,或者在Comparator接口中使用比较器构造方法。
- package codeTemplate.effectiveJava.bean;
-
- public class PhoneNumber implements Comparable
{ - private short areaCode, prefix, lineNum;
- private PhoneArea phoneArea;
-
- @Override
- public int compareTo(PhoneNumber phoneNumber) {
- int result = Short.compare(areaCode, phoneNumber.areaCode);
- if (result == 0) {
- result = Short.compare(prefix, phoneNumber.prefix);
- if (result == 0) {
- result = Short.compare(lineNum, phoneNumber.lineNum);
- }
- }
- return result;
- }
- }
若没有实现Comparable接口,可以使用一个显式的Comparator来代替
- package codeTemplate.effectiveJava.bean;
-
- import lombok.Getter;
- import lombok.Setter;
-
- import java.util.Comparator;
-
- @Getter
- @Setter
- public class PhoneNumber {
- private short areaCode, prefix, lineNum;
- private PhoneArea phoneArea;
- private static final Comparator
COMPARATOR = Comparator.comparingInt((PhoneNumber pn) -> pn.areaCode) - .thenComparingInt(pn -> pn.prefix).thenComparingInt(pn -> pn.lineNum);
-
- public int compareTo(PhoneNumber phoneNumber) {
- return COMPARATOR.compare(this, phoneNumber);
- }
- }