使用Intellij IDEA插件生成使用Guava的equals、hashCode 和toString方法

本文为翻译文章,原文为:Let your IntelliJ IDEA generate good looking equals, hashCode and toString with Google Guava

问题

在Java编程里,我们需要经常编写equals, hashCode 和 toString方法。老实讲,这通常只需要一个模板就能完成。

托各种优秀IDE的福,我们已经不需要自己手动来编写这些代码了。我们可以让IDE使用插件来帮我们完成这些工作。但是仍然有一个问题。通常由IDE自动生成的这些代码都非常难看。让我们来看下面一个POJO:

public class Beer {

    private String brand;
    private String type;
    private int degrees;
    private double alcoholPercentage;
    private List<String> ingredients;

    // constructor
    // getters, setters if needed

}

通用做法

我注意到几乎所有的主流IDE都能够生成符合需求的方法的代码,但是生成的equals、hashCode和toString方法代码通常看起来就像下面这样:

1. equals – long list of IF statements …

@Override
public boolean equals(final Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof Beer)) {
        return false;
    }

    final Beer beer = (Beer) o;

    if (Double.compare(beer.alcoholPercentage, alcoholPercentage) != 0) {
        return false;
    }
    if (degrees != beer.degrees) {
        return false;
    }
    if (!brand.equals(beer.brand)) {
        return false;
    }
    if (!ingredients.equals(beer.ingredients)) {
        return false;
    }
    if (!type.equals(beer.type)) {
        return false;
    }

    return true;
}

2. hashCode – confusing magic numbers, xors and shifts

@Override
public int hashCode() {
    int result;
    long temp;
    result = brand.hashCode();
    result = 31 * result + type.hashCode();
    result = 31 * result + degrees;
    temp = alcoholPercentage != +0.0d ? Double.doubleToLongBits(alcoholPercentage) : 0L;
    result = 31 * result + (int) (temp ^ (temp >>> 32));
    result = 31 * result + ingredients.hashCode();
    return result;
}

3. toString – nasty string concatenation

@Override
public String toString() {
    return "Beer{" +
            "brand='" + brand + '\'' +
            ", type='" + type + '\'' +
            ", degrees=" + degrees +
            ", alcoholPercentage=" + alcoholPercentage +
            ", ingredients=" + ingredients +
            '}';
}

使用Guava库来解决

你有可能已经听过说或者已经使用过Google Guava,但是无论怎样,Google Guava都是一个提供了很多非常使用Java工具的精巧的库。我们可以使用Google Guava来重写上面的三个方法来使得代码显得更好看:

1. equals – army of IF statements transformed to chained call

@Override
public boolean equals(final Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
        return false;
    }
    final Beer other = (Beer) obj;
    return Objects.equal(this.brand, other.brand) && Objects
            .equal(this.type, other.type) && Objects
            .equal(this.degrees, other.degrees) && Objects
            .equal(this.alcoholPercentage, other.alcoholPercentage) && Objects
            .equal(this.ingredients, other.ingredients);
}

2. hashCode – 一行搞定

@Override
public int hashCode() {
    return Objects.hashCode(brand, type, degrees, alcoholPercentage, ingredients);
}

3. toString – consistent chained call

@Override
public String toString() {
    return Objects.toStringHelper(this)
            .add("brand", brand)
            .add("type", type)
            .add("degrees", degrees)
            .add("alcoholPercentage", alcoholPercentage)
            .add("ingredients", ingredients)
            .toString();
}

安装Intellij IDEA插件

对于equals和hashCode方法,在IDEA中还可以使用由Michal Jedynak编写的Equals and HashCode Deluxe Generator来生成代码。你可以在IDEA的插件库中搜索该该插件:

search plugin

使用这个插件非常简单,你只需要在代码编辑器内弹出鼠标右键就可以看到增加的插件选单,或者你也可以使用ALT+INSERT(MAC下使用CTRL+N)快捷键,如图所示:

context menu

至于toString方法,我们只需要在IDEA中增加一个模板即可。使用ALT+INS 快捷键然后选择toString()菜单选项。点击设置按钮并切换到模板(Templates)选项卡。在模板选单页点击”+”按钮:

add toString template

填写新模板的名称(诸如guava tostring等),然后把下面的代码拷贝到模板编辑页里。

public String toString() {
    #set ($autoImportPackages = "com.google.common.base.Objects")
    return Objects.toStringHelper(this)
    #foreach ($member in $members)
        .add("$member.name", $member.accessor)
    #end
        .toString();
}

使用新模板也非常简单,使用ALT+INS快捷键,选择toString(),然后确认选择正确的模板即可:

enter image description here

Enjoy code!