Các trình xây dựng commons / lang rất tuyệt vời và tôi đã sử dụng chúng trong nhiều năm mà không có hiệu suất đáng chú ý (có và không có ngủ đông). Nhưng như Alain viết, cách ổi thậm chí còn đẹp hơn:
Đây là một mẫu Bean:
public class Bean{
private String name;
private int length;
private List<Bean> children;
}
Đây là bằng () và hashCode () được triển khai với Commons / Lang:
@Override
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return new EqualsBuilder()
.append(name, other.name)
.append(length, other.length)
.append(children, other.children)
.isEquals();
} else{
return false;
}
}
và ở đây với Java 7 trở lên (lấy cảm hứng từ Guava):
@Override
public int hashCode(){
return Objects.hash(name, length, children);
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return Objects.equals(name, other.name)
&& length == other.length // special handling for primitives
&& Objects.equals(children, other.children);
} else{
return false;
}
}
Lưu ý: mã này ban đầu được tham chiếu Guava, nhưng như các ý kiến đã chỉ ra, chức năng này đã được giới thiệu trong JDK, do đó, Guava không còn cần thiết nữa.
Như bạn có thể thấy phiên bản Guava / JDK ngắn hơn và tránh các đối tượng trợ giúp không cần thiết. Trong trường hợp bằng, nó thậm chí còn cho phép đánh giá ngắn mạch nếu một Object.equals()
cuộc gọi trước đó trả về sai (công bằng: commons / lang có một ObjectUtils.equals(obj1, obj2)
phương thức với ngữ nghĩa giống hệt nhau có thể được sử dụng thay vì EqualsBuilder
cho phép đoản mạch như trên).
Vì vậy: có, các trình xây dựng lang commons rất thích hơn các phương thức được xây dựng thủ công equals()
và hashCode()
các phương thức (hoặc những quái vật khủng khiếp mà Eclipse sẽ tạo ra cho bạn), nhưng các phiên bản Java 7+ / Guava thậm chí còn tốt hơn.
Và một lưu ý về Hibernate:
hãy cẩn thận về việc sử dụng các bộ sưu tập lười biếng trong các triển khai bằng (), hashCode () và toString () của bạn. Điều đó sẽ thất bại thảm hại nếu bạn không có Phiên mở.
Lưu ý (về bằng ()):
a) trong cả hai phiên bản bằng () ở trên, bạn cũng có thể muốn sử dụng một hoặc cả hai phím tắt này:
@Override
public boolean equals(final Object obj){
if(obj == this) return true; // test for reference equality
if(obj == null) return false; // test for null
// continue as above
b) tùy thuộc vào cách giải thích của bạn về hợp đồng bằng (), bạn cũng có thể thay đổi (các) dòng
if(obj instanceof Bean){
đến
// make sure you run a null check before this
if(obj.getClass() == getClass()){
Nếu bạn sử dụng phiên bản thứ hai, có lẽ bạn cũng muốn gọi super(equals())
bên trong equals()
phương thức của mình . Ý kiến khác nhau ở đây, chủ đề được thảo luận trong câu hỏi này:
đúng cách để kết hợp siêu lớp vào triển khai Guava Object.hashcode ()?
(mặc dù đó là về hashCode()
, cùng áp dụng cho equals()
)
Lưu ý (lấy cảm hứng từ Nhận xét từ kayahr )
Objects.hashCode(..)
(giống như bên dưới Arrays.hashCode(...)
) có thể hoạt động kém nếu bạn có nhiều trường nguyên thủy. Trong những trường hợp như vậy, EqualsBuilder
thực sự có thể là giải pháp tốt hơn.
reflectionEquals
vàreflectionHashcode
; hiệu suất là một kẻ giết người tuyệt đối.