This document describes the @Interned
type annotation, and a
checker (a compiler plugin) for it.
If the plugin issues no warnings for a given program, then all reference
equality tests (e.g., “==
”) in that program
operate on interned types. Interning can save memory (and speed up testing
for equality by permitting use of ==
), but use of
==
on non-interned values can result in subtle bugs. For
example:
Integer x = new Integer(22); Integer y = new Integer(22); System.out.println(x == y); // prints false!
This plugin helps programmers to detect and prevent such bugs.
The Interned checking plugin is distributed as part of the JSR 308 checkers framework.
Contents:
@Interned
In order to perform checking, you must annotate your code with the
@Interned
type annotation, which indicates a type for the
canonical representation of an object:
import checkers.quals.*; // permit use of @Interned ... String s1 = ...; // type is (uninterned) "String" @Interned String s2 = ...; // Java type is "String", but plugin treats as "Interned String"
The type system enforced by the compiler plugin ensures that only interned
values can be assigned to s2
.
To specify that all objects of a given type are interned, annotate the class declaration:
import checkers.quals.*; // permit use of "@Interned" ... public @Interned class MyInternedClass { ... }
This is equivalent to annotating every use of MyInternedClass
,
in a declaration or elsewhere.
For example, enum classes are implicitly so annotated.
Objects of an @Interned
type may be
safely compared using the “==
” operator.
The plugin issues a warning in two cases:
==
” or (“!=
”) is used to
compare objects and the type of at least one operand is not
@Interned
. @Interned
type is used where an
@Interned
type is expected. String literals and the
null
literal are always considered interned, and object creation
expressions (using new
) are never considered
@Interned
unless they are annotated as such.This example shows both sorts of problems:
Object obj; @Interned Object iobj; ... if (obj == iobj) { ... } // checker warning: reference equality test is unsafe iobj = obj; // checker warning: iobj's referent may no longer be interned
To try the @Interned
plugin on a source file that uses
the @Interned
qualifier, use the following command (where
javac
is the JSR 308 compiler):
javac -typeprocessor checkers.interned.InternedChecker examples/InternedExample.java
Compilation will complete without warnings.
To see the checker warn about incorrect usage of annotations, use the following command:
javac -typeprocessor checkers.interned.InternedChecker examples/InternedExampleWithWarnings.java
The compiler will issue a warning regarding violation of the
semantics of @Interned
in the
InternedExampleWithWarnings.java
file.
If you have any problem with the
@Interned
checker, please see “How to report
bugs” for information on reporting bugs, so that we can improve
it in a future release.
Back to the JSR 308 checkers framework.