Object and Reference Immutability using Java Generics Yoav Zibin(1), Alex Potanin(2), Shay Artzi(1), Adam Kiezun(1), and Michael D. Ernst(1) 1) MIT Computer Science and Artificial Intelligence Lab, USA 2) Victoria University of Wellington, New-Zealand Presenting: Ori Arad ([email protected]) – 14/2/07
23
Embed
Object and Reference Immutability using Java Generics
Object and Reference Immutability using Java Generics. Yoav Zibin(1), Alex Potanin(2), Shay Artzi(1), Adam Kiezun(1), and Michael D. Ernst(1) 1) MIT Computer Science and Artificial Intelligence Lab, USA 2) Victoria University of Wellington, New-Zealand - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Object and Reference Immutability using Java Generics
Yoav Zibin(1), Alex Potanin(2), Shay Artzi(1), Adam Kiezun(1), and Michael D. Ernst(1)
1) MIT Computer Science and Artificial Intelligence Lab, USA2) Victoria University of Wellington, New-Zealand
Legend:L List, O object, R ReadOnlyIM Immutable, M Mutable
For example:L< R,O<M> > meansList<ReadOnly, Object<Mutable>>
9/23
Java Array Co-Variance Problem
Read from Array: OK!Write to Array: Problem!
// A is a single-element array of String.String[] a = new String[1];
// B is an array of ObjectObject[] b = a;
// Assign an Integer to b. This would be possible if b really were// an array of Object, but since it really is an array of String,// we will get a java.lang.ArrayStoreException.b[0] = new Integer (1);
// A is a single-element array of String.String[] a = new String[1];
// B is an array of ObjectObject[] b = a;
// Assign an Integer to b. This would be possible if b really were// an array of Object, but since it really is an array of String,// we will get a java.lang.ArrayStoreException.b[0] = new Integer (1);
Solution with IGJ – immutability promise us
only reading no Co-Variance problem
10/23
The Field Rule
legal iff I(o) = Mutable.Example:
Employee<ReadOnly> roE = ...;
roE.address = ...; // Compilation error!
Employee<ReadOnly> roE = ...;
roE.address = ...; // Compilation error!
o.someField = exp;
Typing is guaranteed by several rules.Let I(x) denote the immutability of x
Rule I: Field Assignment Rule
11/23
"Immutability" of Methods
4 new annotations: @ReadOnly, @Mutable, @Immutable and @AssignFields
Example:@Mutable void m()
{...this...} Here: I(this) is Mutable In general: in any method m, I(this)
is the same as I(m) “this” immutability depends on the
context
12/23
Reference-Immutability Rules
Method Invocation Rule:
(not necessarily I(o) = I(m) )
Employee<Mutable> o = ...;o.setAddress(...); // OK since I(o) = Mutable and I(setAddress) = Mutable
o.getAddress(); // OK since I(o) = Mutable and I(getAddress) = ReadOnly
3: public @AssignFields Edge(long id) { this.setId(id); }
4: public @AssignFields synchronized void setId(long id) {
5: this.id = id; }
6: public @ReadOnly synchronized long getId() { return id; }
7: public @Immutable long getIdImmutable() { return id; }
8: public static void print(Edge<ReadOnly> n) {... }
9: }
10: class Graph<I extends ReadOnly> {
11: public Edge<I> lastN;
12: public List<I,Edge<I>> l;
13: public @AssignFields Graph(List<I,Edge<I>> l) { this.l = l; }
14: public @Mutable void addEdge(Edge<I> n) {
15: this.l.add(n); this.lastN = n; }
16: public @ReadOnly Edge<I> getLast() { return this.lastN; }
17: public static <T extends ReadOnly>
18: Edge<T> findEdge(Graph<T> nl, long id) { ... }
19: }
1: class Edge<I extends ReadOnly> {
2: private long id;
3: public @AssignFields Edge(long id) { this.setId(id); }
4: public @AssignFields synchronized void setId(long id) {
5: this.id = id; }
6: public @ReadOnly synchronized long getId() { return id; }
7: public @Immutable long getIdImmutable() { return id; }
8: public static void print(Edge<ReadOnly> n) {... }
9: }
10: class Graph<I extends ReadOnly> {
11: public Edge<I> lastN;
12: public List<I,Edge<I>> l;
13: public @AssignFields Graph(List<I,Edge<I>> l) { this.l = l; }
14: public @Mutable void addEdge(Edge<I> n) {
15: this.l.add(n); this.lastN = n; }
16: public @ReadOnly Edge<I> getLast() { return this.lastN; }
17: public static <T extends ReadOnly>
18: Edge<T> findEdge(Graph<T> nl, long id) { ... }
19: }
ExampleIGJ classes Edge<I> and Graph<I>, with the immutability parameters (and annotations, for this) underlined.
For now:Assume @Immutable is like @ReadOnlyAnd @AssignFields is like @Mutable
14/23
Example:
Line 5: the assignment into this.id is OK If this.id = …; was on line 6 – illegal… Line 3: OK due to Method Rule Line 8: static no annotation, Edge of any
immutability could be pass here…
1: class Edge<I extends ReadOnly> {
2: private long id;
3: public @AssignFields Edge(long id) { this.setId(id); }
4: public @AssignFields synchronized void setId(long id) {
5: this.id = id; }
6: public @ReadOnly synchronized long getId() { return id; }
7: public @Immutable long getIdImmutable() { return id; }
8: public static void print(Edge<ReadOnly> n) {... }
9: }
1: class Edge<I extends ReadOnly> {
2: private long id;
3: public @AssignFields Edge(long id) { this.setId(id); }
4: public @AssignFields synchronized void setId(long id) {
5: this.id = id; }
6: public @ReadOnly synchronized long getId() { return id; }
7: public @Immutable long getIdImmutable() { return id; }
8: public static void print(Edge<ReadOnly> n) {... }
9: }
15/23
Example:
Line 11: a class can pass its immutability parameter to its fields
Line 16: Also return type – no need for overloading Line 12: Transitivity - in an immutable Graph the
field l will contain an immutable list of immutable edges
10: class Graph<I extends ReadOnly> {
11: public Edge<I> lastN;
12: public List<I,Edge<I>> l;
13: public @AssignFields Graph(List<I,Edge<I>> l) { this.l = l; }
14: public @Mutable void addEdge(Edge<I> n) {
15: this.l.add(n); this.lastN = n; }
16: public @ReadOnly Edge<I> getLast() { return this.lastN; }
17: public static <T extends ReadOnly>
18: Edge<T> findEdge(Graph<T> nl, long id) { ... }
19: }
10: class Graph<I extends ReadOnly> {
11: public Edge<I> lastN;
12: public List<I,Edge<I>> l;
13: public @AssignFields Graph(List<I,Edge<I>> l) { this.l = l; }
14: public @Mutable void addEdge(Edge<I> n) {
15: this.l.add(n); this.lastN = n; }
16: public @ReadOnly Edge<I> getLast() { return this.lastN; }
17: public static <T extends ReadOnly>
18: Edge<T> findEdge(Graph<T> nl, long id) { ... }
19: }
16/23
Object Immutability & constructors
What annotation should CTOR be?... @Mutable? problem:
public @Mutable Graph(List<I,Edge<I>> l) {
this.l = l;
this.addEdge( new Edge<Mutable>(0) ); // }
…
List<Immutable,Edge<Immutable>> imList = ...;
new Graph<Immutable>(imList); // An element was added to imList
public @Mutable Graph(List<I,Edge<I>> l) {
this.l = l;
this.addEdge( new Edge<Mutable>(0) ); // }
…
List<Immutable,Edge<Immutable>> imList = ...;
new Graph<Immutable>(imList); // An element was added to imList
@Immutable? Guess not…
17/23
Object Immutability & constructors
Solution: Forth kind of reference immutability: AssignFields
Permit to perform limited side-effects without permitting modification of immutable objects @Mutable method can assign & mutate @AssignFields method can only assign
18/23
Immutability & Assignability
MyClass myObject = new MyClass();
myObject = anotherObject; Assignability
myObject.setField(4); immutability
19/23
Revised rules
Field Rule revised (relaxed): AssignField is not transitive…
Method Rule revised (restricted):
o.someField = ...; is legal if I(o) = Mutableor (I(o) = AssignFields and o=this)
o.m(...) is legal if I(o) is subtype of I(m)and (I(m) = AssignFields implies o=this)
20/23
Example:
Line 5: the assignment into this.id is still OK setId is annotated with @AssignFields I(this)=AssignFields
Line 3: I(this) = AssignFields & I(setId) = AssignFields
1: class Edge<I extends ReadOnly> {
2: private long id;
3: public @AssignFields Edge(long id) { this.setId(id); }
4: public @AssignFields synchronized void setId(long id) {
5: this.id = id; }
6: public @ReadOnly synchronized long getId() { return id;}
7: public @Immutable long getIdImmutable() { return id; }
8: public static void print(Edge<ReadOnly> n) {... }
9: }
1: class Edge<I extends ReadOnly> {
2: private long id;
3: public @AssignFields Edge(long id) { this.setId(id); }
4: public @AssignFields synchronized void setId(long id) {
5: this.id = id; }
6: public @ReadOnly synchronized long getId() { return id;}
7: public @Immutable long getIdImmutable() { return id; }
8: public static void print(Edge<ReadOnly> n) {... }
9: }
21/23
Example:
Line 13: If we will add the following code – it will be illegal in the revised rule (and legal in the old one)
public @mutable Graph(List<I,Edge<I>> l) {
this.l = l;
this.l.get(0).setId(42); // }
public @mutable Graph(List<I,Edge<I>> l) {
this.l = l;
this.l.get(0).setId(42); // }
New Rule:new SomeClass<X,…>(…) is legal only if
X = Mutable and this CTOR is not marked as @Mutable, or X = Imuutable and this CTOR is not marked as @Immutable (X = readOnly & X=AssignFileds are illegal)
22/23
Future Work
Plug-in for IDE (e.g. Eclipse) A WriteOnly immutability parameter @readable notation for field