本文向大家介绍一些 Java 编程行话,即 Java 惯用语,用以描述某些特性、功能、设计解决方案等。
我们还将学习设计和编写应用程序代码中最流行和最有用的实践。
读完本文,大家会彻底弄明白:其他 Java 程序员在讨论设计决策和所使用的功能时,讨论的内容到底是什么意思。
本文涉及以下主题:
Java 行业惯用语、实现及用法
最佳设计实践
代码为人而写
测试——通向高质量代码的捷径
01、Java 行业惯用语、实现及用法
除了作为专业人员之间交流手段外,编程惯用语也是久经考验的编程解决方案和常见实践。
这些都不是直接产生于语言规范,而是来自编程经验。我们将讨论最常用的惯用语。
至于惯用语的完整列表,可以在 Java 官方文档中查找和学习。
1●equals()方法和 hashCode()方法
java.lang.Object 类中,equals()方法和 hashCode()方法的默认实现,如下所示。
public boolean equals(Object obj) {
return (this == obj);
}
/**
* Whenever it is invoked on the same object more than once during
* an execution of a Java application, the hashCode method
* must consistently return the same integer...
* As far as is reasonably practical, the hashCode method defined
* by class Object returns distinct integers for distinct objects.
*/
@HotSpotIntrinsicCandidate
public native int hashCode();
可以看到,equals()方法的默认实现仅比较指向对象存储地址的内存引用。
类似地,从注释(引自源代码)中可以看出,hashCode()方法为相同的对象返回相同的整数,为不同的对象返回不同的整数。
下面用 Person 类来演示,具体如下。
public class Person {
private int age;
private String firstName, lastName;
public Person(int age, String firstName, String lastName) {
this.age = age;
this.lastName = lastName;
this.firstName = firstName;
}
public int getAge() { return age; }
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
}
对于 equals()方法和 hashCode()方法的默认行为,举例如下:
Person person1 = new Person(42, "Nick", "Samoylov");
Person person2 = person1;
Person person3 = new Person(42, "Nick", "Samoylov");
System.out.println(person1.equals(person2)); //prints: true
System.out.println(person1.equals(person3)); //prints: false
System.out.println(person1.hashCode()); //prints: 777874839
System.out.println(person2.hashCode()); //prints: 777874839
System.out.println(person3.hashCode()); //prints: 596512129
person1 引用和 person2 引用及其散列码都是相等的,因为这两个引用指向相同的对象(相同的内存区域,以及相同的地址),而 person3 引用指向另一个对象。
在实践中,经常希望对象相等是基于对象的全部或部分属性值。
下面是 equals()和 hashCode()方法的一个典型实现。
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if(!(o instanceof Person)) return false;
Person person = (Person)o;
return getAge() == person.getAge() &&
Objects.equals(getFirstName(), person.getFirstName()) &&
Objects.equals(getLastName(), person.getLastName());
}
@Override
public int hashCode() {
return Objects.hash(getAge(), getFirstName(), getLastName());
}
这样的实现在以前是比较复杂的,现在使用 java.util.Objects 实用程序令这样的实现简单多了。
特别值得注意的是,Objects.equals()方法还能处理 null 值。
将上述 equals()和 hashCode()方法的实现添加到 Person1 类中,执行同样的比较操作。
具体如下:
Person1 person1 = new Person1(42, "Nick", "Samoylov");
Person1 person2 = person1;
Person1 person3 = new Person1(42, "Nick", "Samoylov");
System.out.println(person1.equals(person2)); //prints: true
System.out.println(person1.equals(person3)); //prints: true
System.out.println(person1.hashCode()); //prints: 2115012528
System.out.println(person2.hashCode()); //prints: 2115012528
System.out.println(person3.hashCode()); //prints: 2115012528