1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.interning.qual.InternMethod;
import org.checkerframework.checker.interning.qual.Interned;
public @Interned class InternedClass2 {
private final int i;
// @UnknownInterned is the default annotation on constructor results even for @Interned classes.
private InternedClass2(int i) {
// Type of "this" inside a constructor of an @Interned class is @UnknownInterned.
// :: error: (assignment.type.incompatible)
@Interned InternedClass2 that = this;
this.i = i;
}
InternedClass2 factory(int i) {
// :: error: (interned.object.creation) :: error: (method.invocation.invalid)
new InternedClass2(i).someMethod(); // error, call to constructor on for @Interned class.
(new InternedClass2(i)).intern(); // ok, call to constructor receiver to @InternMethod
((((new InternedClass2(i))))).intern(); // ok, call to constructor receiver to @InternMethod
return new InternedClass2(i).intern(); // ok, call to constructor receiver to @InternMethod
}
void someMethod() {
// Type of "this" inside a method (not marked @InternedMethod) is @Interned,
// assuming the method is declared in an @Interned class.
@Interned InternedClass2 that = this; // ok
}
private static Map<Integer, InternedClass2> pool = new HashMap<>();
@InternMethod
public InternedClass2 intern() {
// Type of "this" inside an @InternMethod is @UnknownInterned
// :: error: (assignment.type.incompatible)
@Interned InternedClass2 that = this;
if (!pool.containsKey(this.i)) {
// The above check proves "this" is interned.
@SuppressWarnings("interning:assignment.type.incompatible")
@Interned InternedClass2 internedThis = this;
pool.put(this.i, internedThis);
}
return pool.get(this.i);
}
@Override // ok, no override invalid receiver error is issued.
public String toString() {
@Interned InternedClass2 that = this; // ok
return super.toString();
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
InternedClass2 that = (InternedClass2) object;
return i == that.i;
}
@Override
public int hashCode() {
return i;
}
public boolean hasNodeOfType(Class<?> type) {
if (type == this.getClass()) {
return true;
}
return false;
}
}
|