A következő címkéjű bejegyzések mutatása: Immutable. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: Immutable. Összes bejegyzés megjelenítése

2014. május 7., szerda

import groovy.transform.Immutable

A Groovy szemlélet ellentétben a Java-val a nyiltságról szól. Minden alapértelmezetten publikus, nem kell bajlódnunk getter/setter írásával (persze a háttérben történnek dolgok, most a szemléletről beszélek), a metaclass jóvóltából módosítani lehet osztályok működését, és még sorolhatnám. A most bemutatásra kerülő lehetőség mégis sokszor tud hasznos lenni.
@groovy.transform.Immutable
class A { Integer a }
new A()
A kódot futtatva az alábbi eredményt kapjuk:
org.codehouse.groovy.runtime.metaclass.MethodSelectionException: Could not find which method <init>() to invoke from list:
public A#<init>(java.util.HashMap)
public A#<init>(java.lang.Integer)
Tehát a fordító nem tudta eldönteni, hogy melyik konstruktorát használja az osztálynak, ami azt jelenti, hogy az ilyen intefésszel ellátott osztályok tagjainak kötelező kezdő értéket adnunk.
@groovy.transform.Immutable
class A { Integer a }
new A(0).a = 1
Mikor megpróbáljuk módosítani az adattagot, egy kivétellel hálálja meg a JVM.
groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: a for class: A
A történet eddig nem nagy szám, mert az alábbi kódsorok ugyanezt az eredményt adják (kicsit több gépeléssel):
class A {
final Integer a
A(a) { this.a = a }
}
new A(0).a = 1
De mi a helyzet ezzel:
@groovy.transform.Immutable
class A { List a }
A a = new A([])
a.a << 1
Ennél az esetnél mutatkozik meg, hogy az annotáció mivel több egy mezei final módosítónál. A listánk bizony egy Collection.UnmodifiableRandomAccessList lett. Tovább kísérletezve mi történik, ha egy saját osztályt teszünk adattagként A-ba.
@groovy.transform.Immutable
class A { B b }
class B { Integer b }
A a = new A(new B())
java.lang.RuntimeException: @Immutable processor doesn't know how to handle field 'b' of type 'B' while constructing class A.
@Immutable classes only support properties with effectively immutable types including:
- Strings, primitive types, wrapper types, BigInteger and BigDecimal, enums
- other @Immutable classes and known immutables (java.awt.Color, java.net.URI)
- Cloneable classes, collections, maps and arrays, and other classes with special handling (java.util.Date)
Other restrictions apply, please see the groovydoc for @Immutable for further details
Amennyiben ellátunk egy osztályt ezzel az annotációval, a Groovy fordító garantálja nekünk, az osztály módosíthatatlan lesz, hiszen kötelezően minden adattagjának szintén módosíthatatlannak kell lennie. Bővebb információ a GroovyDoc-ban, amit fontos kiemelni, hogy @Target({ElementType.TYPE}), tehát osztályokra, interfészekre, és enumokra lehet tenni az annotációt, bár utóbbi 2 esetben fordítási hibát fogunk kapni.
Házi feladat a a groovy.transform csomag átböngészése, sok hasznos eszköz lapul még benne.