package checkers.jimmu.examples; import checkers.jimmu.quals.*; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.Set; /** * Example on enforcing anonymity of constructors. * * @author saf */ public class Anonymity { static Random r; private void init() { r = new Random(); } public static class A { List<Integer> list; Set<Integer> set; public A() { list = new LinkedList<Integer>(); set = new HashSet<Integer>(); } @Anonymous public A(List<Integer> l) { Initializer i = new Initializer(); /* The Initializer 'i' might observe the state of the constructed object * while it is not yet fully initialized. Thus, the call is * prohibited in an @Anonymous constructor */ i.initialize(this, l); list = l; } @Anonymous public A(Integer n) { this.prepareSet(n); /* OK */ prepareSet(n); /* OK */ prepareList(n); /* Error: the called method is not @Anonymous and might leak references to a partially constructed object. */ } @Anonymous protected void prepareSet(Integer n) { for (int i = 1; i <= n; i++) set.add(i); } protected void prepareList(Integer n) { for (int i = 1; i <= n; i++) list.add(i); } @ReadOnly @Anonymous public Set<Integer> getSet() { return set; } } public static class Initializer { void initialize(A a, List<Integer> l) { for (Integer i : l) a.getSet().add(i); } } public static void main(String [] args) { /* This call issues a warning: 'a' is constructed using a non-anonymous * constructor. Hence, the state of the partially-constructed 'a' may leak * outside the constructor. */ @Immutable A a = new /*@Immutable*/ A(); @Immutable A b = new /*@Immutable*/ A(5); System.out.println(b.getSet().toString()); } }