| import java.util.HashMap; |
| import java.util.Map; |
| import org.checkerframework.checker.interning.qual.*; |
| |
| public class StringIntern { |
| |
| // It would be very handy (and would eliminate quite a few annotations) |
| // if any final variable that is initialized to something interned |
| // (essentially, to a literal) were treated as implicitly @Interned. |
| final String finalStringInitializedToInterned = "foo"; // implicitly @Interned |
| final String finalString2 = new String("foo"); |
| static final String finalStringStatic1 = "foo"; // implicitly @Interned |
| static final String finalStringStatic2 = new String("foo"); |
| |
| static class HasFields { |
| static final String finalStringStatic3 = "foo"; // implicitly @Interned |
| static final String finalStringStatic4 = new String("foo"); |
| } |
| |
| static class Foo { |
| private static Map<Foo, @Interned Foo> pool = new HashMap<>(); |
| |
| @SuppressWarnings("interning") |
| public @Interned Foo intern() { |
| if (!pool.containsKey(this)) { |
| pool.put(this, (@Interned Foo) this); |
| } |
| return pool.get(this); |
| } |
| } |
| |
| // Another example of the "final initialized to interned" rule |
| final Foo finalFooInitializedToInterned = new Foo().intern(); |
| |
| public void test(@Interned String arg) { |
| String notInternedStr = new String("foo"); |
| @Interned String internedStr = notInternedStr.intern(); |
| internedStr = finalStringInitializedToInterned; // OK |
| // :: error: (assignment) |
| internedStr = finalString2; // error |
| @Interned Foo internedFoo = finalFooInitializedToInterned; // OK |
| if (arg == finalStringStatic1) {} // OK |
| // :: error: (not.interned) |
| if (arg == finalStringStatic2) {} // error |
| if (arg == HasFields.finalStringStatic3) {} // OK |
| // :: error: (not.interned) |
| if (arg == HasFields.finalStringStatic4) {} // error |
| } |
| |
| private @Interned String base; |
| static final String BASE_HASHCODE = "hashcode"; |
| |
| public void foo() { |
| if (base == BASE_HASHCODE) {} |
| } |
| |
| public @Interned String emptyString(boolean b) { |
| if (b) { |
| return ""; |
| } else { |
| return (""); |
| } |
| } |
| } |