import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Unmodifiable; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; public class MutabilityBasics { @Unmodifiable static List emptyList() { return Collections.emptyList(); } @Contract(mutates = "param") static > void sort(List collection) { Collections.sort(collection); } @Contract(mutates = "param1") static > void addAll(Collection collection, List other) { sort(other); collection.addAll(other); } // Purity implies that no arguments should be changed @Contract(pure = true) static > T min(List list) { sort(list); return list.get(0); } interface Point { int get(); @Contract(mutates = "this") void set(int x); @Contract(pure = true) default void setZero() { // cannot modify itself (call mutating method), because declared as pure set(0); } } @Unmodifiable static Point getZero() { return new Point() { @Override public int get() { return 0; } @Override public void set(int x) { throw new UnsupportedOperationException(); } }; } // Differs from getZero as getZero() is considered as getter with predefined value @Unmodifiable static Point zero() { return getZero(); } @Unmodifiable List list = Arrays.asList("foo", "bar", "baz"); void test() { List collection = emptyList(); sort(collection); sort(MutabilityBasics.emptyList()); getZero().set(1); zero().set(1); sort(list); } }