#TECH

AutoValue- Say bye bye to value classes boilerplate

We all have worked with Value Classes in our projects. A value type is simply an immutable object whose equality is based on property values, as opposed to identity. For example, let’s create a class with data for Employee. There are some properties in this class that can be accessed using a getter. This class also overrides equals(Object), toString(), hashCode() and this is a very common pattern for any project. Here is the sample of Employee class. The sample project can be found on GitHub.

public class EmployeeData {

    private final long id;
    private final String name;
    private final boolean status;

    public EmployeeData(long id, String name, boolean status) {
        this.id = id;
        this.name = name;
        this.status = status;
     }
    public long getId() { return id; }

    public String getName() { return name; }

    public boolean getStatus() { return status; }

        @Override
    public String toString() {
        return "EmployeeData{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", status=" + status +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        EmployeeData that = (EmployeeData) o;

        if (id != that.id) return false;
        if (status != that.status) return false;
        if (name != null ? !name.equals(that.name) : that.name != null) return false;
    }

    @Override
    public int hashCode() {
        int result = (int) (id ^ (id >>> 32));
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + status;
        return result;
    }
}

As you can see in the above example that there are 50-60 lines of code for a common class and there are many classes like this in the project. The problem with this code is the maintenance, analysis, and review. When there is a need to add one more attribute; we must take several steps like- declare a parameter, include it in the constructor, create a getter for that attribute, add that attribute in equals(Object), hashCode() and toString() method. If there is some mistake during the process the whole code will fail when while accessing this class. There is a library to overcome this problem and it also goes ahead and provides a Parcelable implementation, so that we don’t have to implement it ourselves.

Google AutoValue

AutoValue

The above problem can be overcome with Google’s solution to the value type issue i.e AutoValue. The above lengthy class can be converted into a more concise class that will contain 10-20 lines of code. The developer only needs to declare a class and all the other heavy work is taken care of by AutoValue. Let’s see how we can set up AutoValue in our Android Studio.

1. Add the following dependency to your build.gradle file-

dependencies {
    provided 'com.google.auto.value:auto-value:1.5.2'
    annotationProcessor 'com.google.auto.value:auto-value:1.5.2'
}

2. Add @AutoValue annotation to that class.

3. Make the class abstract since its implementation will be generated, and can not be created manually.

4. Remove the earlier attributes and implement abstract methods in that class corresponding to the attributes.

After these steps, your class should look like this-

@AutoValue
public abstract class EmployeeData {
    abstract long id();
    abstract String name();
    abstract boolean status();
  }

Looks great, isn’t it?

As now we have our class as abstract so we must define a way to create an instance of it. AutoValue class allows new instance by publishing a static method create.

public static EmployeeData create(long id, String name, boolean status) {
        return builder().name(name).id(id).status(status).build();
    }

Note: AutoValue classes are generated during build time. You must rebuild your project every time you make any changes in the definitions.

At some point, using constructor with several parameters might become unmanageable. Don’t worry, AutoValue allows Builder pattern as well. That means we can generate classes that allow the initialization of objects using the Builder Pattern. To create a Builder, we must define an internal abstract class, as the sample below.

@AutoValue.Builder
    public interface Builder {

        Builder id(long value);

        Builder name(String value);

        Builder status(boolean value);

        Builder address(List<Address> address);

        EmployeeData build();

    }

Now replace the create method by the builder() method, written as below-

static Builder builder() {
        return new AutoValue_EmployeeData.Builder();
    }

Now we can create class as-

EmployeeData employeeData = EmployeeData.builder()
  .id(1)
  .name("Hulk")
  .status(0)
  .build();

Our class is now much simpler. We can now declare new attribute very easily with no hassle.

Extension

The AutoValue also has a very useful feature called AutoValue Extensions. There are many extensions that AutoValue supports. For example-

  • Parcelable
  • JSON
  • Moschi
  • Gson

We just need to add the below-mentioned dependency to support Parcelable classes.

annotationProcessor 'com.ryanharter.auto.value:auto-value-parcel:0.2.6'

Now we just have to make our EmployeeData class implement Parcelable. All the methods for this interface will be generated by the extension, the developer doesn’t need to write any more code.

Conclusion

AutoValue is the only solution to the value class problem in Java having characteristics like-

  • No runtime dependencies
  • API-Invisible
  • Negligible cost to performance
  • Very few limitations on what your class can do

Below is an excerpt mentioned in the official documentation-

AutoValue is a great tool for eliminating the drudgery of writing mundane value classes in Java. It encapsulates much of the advice in Effective Java Chapter 2 and frees you to concentrate on the more interesting aspects of your program. The resulting program is likely to be shorter, clearer, and freer of bugs. Two thumbs up.

Joshua Bloch, author, Effective Java

You might also like