您是否看过Java中Object类的javadoc? 大概。 您倾向于时不时地到达那里,然后沿着继承树进行挖掘。 您可能已经注意到的一件事是,每个类都必须继承许多方法。 实现自己而不是坚持使用原始方法的最喜欢的方法可能是.toString()、. equals()和.hashCode()( Per-ÅkeMinborg在本文中很好地描述了为什么应该始终实现这两种方法) )。
但是这些方法显然还不够。 许多人从标准库(如Comparable和Serializable)中混合使用其他接口。 但这真的很明智吗? 为什么每个人都想如此严重地自己实现这些方法? 好吧,如果您打算将它们存储在HashMap之类的文件中并希望控制哈希冲突,那么实现自己的.equals()和.hashCode()方法可能很有意义,但是compareTo()和toString()呢?
在本文中,我将介绍一种在Speedment开源项目中使用的软件设计方法,其中将对对象进行操作的方法实现为存储在变量中的功能引用,而不是覆盖内置在方法中的Java。 这有几个优点。 您的POJO将更短,更简洁,可以重复使用通用操作而无需继承,并且可以灵活地在不同配置之间进行切换。
原始码
让我们从下面的示例开始。 我们有一个典型的Java类,名为Person。 在我们的应用程序中,我们希望按Set的顺序打印每个人的名字,其后跟姓氏(以防两个人共享相同的名字)。
人.java
public class Person implements Comparable<Person> {private final String firstname;private final String lastname;public Person(String firstname, String lastname) {this.firstname = firstname;this.lastname = lastname;}public String getFirstname() {return firstname;}public String getLastname() {return lastname;}@Overridepublic int hashCode() {int hash = 7;hash = 83 * hash + Objects.hashCode(this.firstname);hash = 83 * hash + Objects.hashCode(this.lastname);return hash;}@Overridepublic boolean equals(Object obj) {if (this == obj) return true;if (obj == null) return false;if (getClass() != obj.getClass()) return false;final Person other = (Person) obj;if (!Objects.equals(this.firstname, other.firstname)) {return false;}return Objects.equals(this.lastname, other.lastname);}@Overridepublic int compareTo(Person that) {if (this == that) return 0;else if (that == null) return 1;int comparison = this.firstname.compareTo(that.firstname);if (comparison != 0) return comparison;comparison = this.lastname.compareTo(that.lastname);return comparison;}@Overridepublic String toString() {return firstname + " " + lastname;}
}
Main.java
public class Main {public static void main(String... args) {final Set people = new HashSet<>();people.add(new Person("Adam", "Johnsson"));people.add(new Person("Adam", "Samuelsson"));people.add(new Person("Ben", "Carlsson"));people.add(new Person("Ben", "Carlsson"));people.add(new Person("Cecilia", "Adams"));people.stream().sorted().forEachOrdered(System.out::println);}
}
输出量
run:
Adam Johnsson
Adam Samuelsson
Ben Carlsson
Cecilia Adams
BUILD SUCCESSFUL (total time: 0 seconds)
Person在此处实现了几种方法来控制流的输出。 hashCode()和equals()方法确保不能将重复的人添加到集合中。 sorted操作使用compareTo()方法产生所需的顺序。 重写的toString()方法最终控制了在调用System.out.println()时应如何打印每个Person。 您认识这种结构吗? 您几乎可以在几乎所有的Java项目中找到它。
替代代码
除了将所有功能都放入Person类之外,我们还可以尝试使其尽可能保持清洁,并使用功能性引用来处理这些修饰。 我们使用equals,hashCode,compareTo和toString删除所有样板,而是引入两个静态变量COMPARATOR和TO_STRING。
人.java
public class Person {private final String firstname;private final String lastname;public Person(String firstname, String lastname) {this.firstname = firstname;this.lastname = lastname;}public String getFirstname() {return firstname;}public String getLastname() {return lastname;}public final static Comparator<Person> COMPARATOR =Comparator.comparing(Person::getFirstname).thenComparing(Person::getLastname);public final static Function<Person, String> TO_STRING =p -> p.getFirstname() + " " + p.getLastname();
}
Main.java
public class Main {public static void main(String... args) {final Set people = new TreeSet<>(Person.COMPARATOR);people.add(new Person("Adam", "Johnsson"));people.add(new Person("Adam", "Samuelsson"));people.add(new Person("Ben", "Carlsson"));people.add(new Person("Ben", "Carlsson"));people.add(new Person("Cecilia", "Adams"));people.stream().map(Person.TO_STRING).forEachOrdered(System.out::println);}
}
输出量
run:
Adam Johnsson
Adam Samuelsson
Ben Carlsson
Cecilia Adams
BUILD SUCCESSFUL (total time: 0 seconds)
这种方法的好处是,我们现在可以在不更改Person类的情况下替换打印的顺序和格式。 这将使代码更易于维护,更易于重用,而不是说编写起来更快。
翻译自: https://www.javacodegeeks.com/2016/02/cleaner-responsibilities-get-rid-equals-compareto-tostring.html