[英]Use inheritance to reuse toString/equals/hashCode
Does it bad practice inherit class to reuse toString/equals/hashCode (that actually based on reflection and use actual class field for it)? 不好的做法是继承类以重用toString / equals / hashCode(实际上基于反射并为其使用实际的类字段)吗? For example:
例如:
public abstract class SomeAbstractObject {
private List<Field> collectTransientFields() {
//
return Arrays.stream(getClass().getDeclaredFields())
.filter((f) -> f.getAnnotation(Transient.class) != null)
.collect(Collectors.toList());
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, DEFAULT_STYLE);
}
@Override
public boolean equals(Object o) {
//
List<String> transients = collectTransientFields().stream()
.map(Field::getName)
.collect(Collectors.toList());
return EqualsBuilder.reflectionEquals(this, o, transients);
}
@Override
public int hashCode() {
List<String> transients = collectTransientFields().stream()
.map(Field::getName)
.collect(Collectors.toList());
return HashCodeBuilder.reflectionHashCode(this, transients);
}
private List<Field> collectTransientFields() {
//
return Arrays.stream(getClass().getDeclaredFields())
.filter((f) -> f.getAnnotation(Transient.class) != null)
.collect(Collectors.toList());
}
class A extends SomeAbstractObject
class B extends SomeAbstractObject
I benchmarked this implementation of hashCode and IDE-generated one. 我对hashCode和IDE生成的该实现的基准进行了基准测试。 IDE-generated 10 000 faster for two-field class.
IDE为两场课程生成的速度快了10000。
On the other hand there is even library (jakarta) that provide this reflection functionality. 另一方面,甚至有提供此反射功能的库(雅加达)。
So I have two question: 所以我有两个问题:
Your code as a general implementation for equals
and hashCode
is in my eyes not a good idea for a couple of reasons: 在我看来,将代码作为
equals
和hashCode
的通用实现不是一个好主意,原因有以下几个:
getDeclaredFields
only returns the fields of the "current" class and no fields of a superclass. getDeclaredFields
仅返回“当前”类的字段,而不返回超类的字段。 Your actual implementation of equals
and hashCode
would produce wrong results in such a case. equals
和hashCode
实际实现会产生错误的结果。 transient
. transient
。 For non-serializable classes this is quite uncommon and is therefor easily forgotten. I'm not sure why you want such a thing anyway, the five minutes you might save while implementing a new class by not writing a distinguished equals
and hashCode
method are easily beaten by the time you need to track down a bug that might result from the generic implementation. 我不确定为什么还是要这样,在不
hashCode
可能由以下原因导致的错误时,不编写可区分的equals
和hashCode
方法在实现新类时可能节省的五分钟时间通用实现。 You have to write a testcase for equals
and hashCode
anyway, even if its implementation is generic, so I don't see a real benefit here. 无论如何,您都必须为
equals
和hashCode
编写一个测试用例,即使其实现是通用的,因此在这里我看不到真正的好处。
Edit, final thought: If you have a problem and you think of solving it by using reflection, thing again. 编辑,最后的想法:如果您有问题,并且想通过反射来解决,那就再做一次。 Reflection is a powerful tool but can lead to so many new problems that you should avoid it wherever possible.
反射是一个功能强大的工具,但会导致许多新问题,因此应尽可能避免使用它。 In other words: Reflection is a very specific hammer for very specific nails.
换句话说:反射是针对非常特殊的指甲的非常特殊的锤子。 Don't try to use it for other types.
不要尝试将其用于其他类型。
Having the semantically correct equals() and hashCode() implementations for a class is crucial for many parts of the Java library, and it deserves attention to details. 对于Java类的许多部分,在类上具有语义正确的equals()和hashCode()实现对于Java库的许多部分都是至关重要的,并且应注意细节。
Using reflection for equals() and hashCode() will blindly compare all fields. 对equals()和hashCode()使用反射将盲目地比较所有字段。 Although that will be OK for many cases (where your class is just a collection of data), there are exceptions.
尽管在许多情况下(您的类只是数据的集合)可以这样做,但也有例外。 What about fields like "id", "lastChangedDate", "status" and so on?
那么“ id”,“ lastChangedDate”,“ status”等字段呢? It's quite plausible to not include them in the comparison.
在比较中不包括它们是很合理的。
I prefer to decide for every single class which fields to compare and which not, and I'd recommend against inheriting a default behaviour that can't know anything about my specific class. 我更愿意为每个类决定要比较的字段,而不是要比较的字段,并且建议不要继承对我的特定类一无所知的默认行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.