File: StringIntern.java

package info (click to toggle)
checker-framework-java 3.2.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 22,840 kB
  • sloc: java: 145,910; xml: 839; sh: 518; makefile: 401; perl: 26
file content (64 lines) | stat: -rw-r--r-- 2,281 bytes parent folder | download | duplicates (3)
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
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.type.incompatible)
        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 ("");
        }
    }
}