package chapter; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.GuardedBy; import org.checkerframework.checker.lock.qual.GuardedByBottom; import org.checkerframework.checker.lock.qual.GuardedByUnknown; public class Strings { final Object lock = new Object(); // Tests that @GuardedBy({}) is @ImplicitFor(typeNames = { java.lang.String.class }) void StringIsGBnothing( @GuardedByUnknown Object o1, @GuardedBy("lock") Object o2, @GuardSatisfied Object o3, @GuardedByBottom Object o4) { //:: error: (assignment.type.incompatible) String s1 = (String) o1; //:: error: (assignment.type.incompatible) String s2 = (String) o2; //:: error: (assignment.type.incompatible) String s3 = (String) o3; String s4 = (String) o4; // OK } // Tests that the resulting type of string concatenation is always @GuardedBy({}) // (and not @GuardedByUnknown, which is the LUB of @GuardedBy({}) (the type of the // string literal "a") and @GuardedBy("lock") (the type of param)) void StringConcat(@GuardedBy("lock") MyClass param) { { String s1a = "a" + "a"; //:: error: (lock.not.held) String s1b = "a" + param; //:: error: (lock.not.held) String s1c = param + "a"; //:: error: (lock.not.held) String s1d = param.toString(); String s2 = "a"; //:: error: (lock.not.held) s2 += param; String s3 = "a"; // In addition to testing whether "lock" is held, tests that the result of a string concatenation has type @GuardedBy({}). //:: error: (lock.not.held) String s4 = s3 += param; } synchronized (lock) { String s1a = "a" + "a"; String s1b = "a" + param; String s1c = param + "a"; String s1d = param.toString(); String s2 = "a"; s2 += param; String s3 = "a"; // In addition to testing whether "lock" is held, tests that the result of a string concatenation has type @GuardedBy({}). String s4 = s3 += param; } } class MyClass { Object field = new Object(); } }