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: