AutoValue

Kategória: Java külső könyvtárak.

Problémafelvetés

Tekintsük a következő osztályt:

public class PointA {
    private int x;
    private int y;
 
    public PointA(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
 
    public int getX() {
        return x;
    }
 
    public int getY() {
        return y;
    }
}

Valósítsuk meg a következőt:

        PointA pointA1 = new PointA(2, 3);
        System.out.println(pointA1);
        PointA pointA2 = new PointA(2, 3);
        System.out.println(pointA2);
        System.out.println("A1.equals(A2) = " + pointA1.equals(pointA2));

Az eredmény nem pont az, amit elvárunk:

hu.faragocsaba.autovalueexample.PointA@15db9742
hu.faragocsaba.autovalueexample.PointA@6d06d69c
A1.equals(A2) = false

A példa továbbgondolása

Nyilván meg kell valósítani az equals(), hashCode() és toString() metódusokat:

public class PointB {
    private int x;
    private int y;
 
    public PointB(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
 
    public int getX() {
        return x;
    }
 
    public int getY() {
        return y;
    }
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PointB other = (PointB) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }
 
    @Override
    public String toString() {
        return "PointB [x=" + x + ", y=" + y + "]";
    }
}

Átírva a főprogramot:

        PointB pointB1 = new PointB(2, 3);
        System.out.println(pointB1);
        PointB pointB2 = new PointB(2, 3);
        System.out.println(pointB2);
        System.out.println("B1.equals(B2) = " + pointB1.equals(pointB2));

Azt kapjuk, amit várunk:

PointB [x=2, y=3]
PointB [x=2, y=3]
B1.equals(B2) = true

AutoValue

Ám ezzel van pár probléma:

  • Igen hosszú lett a kód.
  • A generált kód áttekinthetetlen, kézzel megírva pedig lassú, unalmas és könnyű hibázni.
  • Kiterjesztés esetén könnyen megfeledkezünk ezekről a generált részekről.

Erre a problémára kínál megoldást az auto-value. Először ássuk a kódot!

import com.google.auto.value.AutoValue;
 
@AutoValue
public abstract class PointC {
    static PointC create(int x, int y) {
        return new AutoValue_PointC(x, y);
    }
 
    abstract int x();
    abstract int y();
}

A hozzá tartozó főprogram alig változik:

        PointC pointC1 = PointC.create(2, 3);
        System.out.println(pointC1);
        PointC pointC2 = PointC.create(2, 3);
        System.out.println(pointC2);
        System.out.println("C1.equals(C2) = " + pointC1.equals(pointC2));

Az eredmény pedig kb. az, amit elvárunk:

PointC{x=2, y=3}
PointC{x=2, y=3}
C1.equals(C2) = true

Csakhogy ez sem jön ingyen! Az egy dolog, hogy meg kell adni függőségként magát az annotációt. A pom.xml vonatkozó része:

        <dependency>
            <groupId>com.google.auto.value</groupId>
            <artifactId>auto-value-annotations</artifactId>
            <version>1.7</version>
        </dependency>

A másik, hogy meg kell adni a feldolgozót is. Elvileg ez az egyik lehetőség:

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>com.google.auto.value</groupId>
                            <artifactId>auto-value</artifactId>
                            <version>1.7</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

Csakhogy ez (nálam) nem működött! A másik lehetőség: beletenni ezt is a függőségek közé:

        <dependency>
            <groupId>com.google.auto.value</groupId>
            <artifactId>auto-value</artifactId>
            <version>1.7</version>
            <optional>true</optional>
        </dependency>

Ez viszont túl sok felesleges függőséget is behozhat: az annotáció maga alig pár kilobájt, a feldolgozó (amely ráadásul az annotációt nem is tartalmazza!) pedig közel 2 megabájt. És van még egy szépséghibája: fordítási hibát jelez az Eclipse. Biztos meg lehet ezt is oldani valahogy, de kicsit az az érzésem, hogy a megoldandó problémák túlnőnek az eredetin.

További információk:

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License