lundi 19 février 2018

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)? For example:

public abstract class AbstractObject {

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 AbstractObject
class B extends AbstractObject

I benchmarked this implementation of hashCode and IDE-generated one. IDE-generated 10 000 faster for two-field class.

On the other hand there is even library (jakarta) that provide this reflection functionality.

So I have two question:

  1. Is it ok to inherit classes for reuse toString/equals/hashCode functionality
  2. Is it ok to use reflection-based implementation of toString/equals/hashCode instead of code-generated or human-written one




Aucun commentaire:

Enregistrer un commentaire