@Documented @Retention(value=RUNTIME) @Target(value=TYPE) public @interface Containable
static method must be annotated
@Borrowed("this");
@Unique("return");
and
@Containable, and
@Unique or @UniqueInRegion.
A field may have an array type if the array is 1-dimensional and the base type of the array is a primitive type.
Only the non-static fields of the class are affected by this annotation. Containability is only interesting when the state of a referenced object is being aggregated into a region of the referencing object. Aggregation only applies to non-static fields, thus containability is not interesting for static fields.
Typically, subtypes of the annotated type must be explicitly annotated
@Containable as well. It is a modeling error if they are
not. This annotation has two attributes, implementationOnly and
verify, that control how subtypes of an Containable type
must be annotated. The implementationOnly attribute indicates that
the implementation of the annotated class should be assured without making a
general statement about the visible behavior of the type or its subtypes.
There are several rules with regards to the implementationOnly
attribute on Containable types:
false when
Containable appears on an interface, because interfaces do not have
an implementation.Containable must
be annotated with Containable; classes that implement an interface
annotated with Containable must be annotated with
@Containable(implementationOnly=false).Containable, but that is not verifiable using the syntactic and
annotation constraints described above. For this case, we provide the
"escape hatch" of turning off tool verification for the annotation with the
verify attribute. For example,
@Containable(verify=false) would skip tool verification
entirely.
A type may not be annotated with both @Containable and
@NotContainable.
An annotation type declaration may not be annotated with
@Containable.
When the annotated type has formal type parameters, the parameters are all
given the annotation bound
@ThreadSafe. If the attribute
allowReferenceObject is true
then the bound @ThreadSafe or
@ReferenceObject is used instead. Unlike
bounds introduced with @AnnotationBounds, these bounds are only
checked when the type is used in a context that requires the type to be
containable. In contexts where the containability is not interesting, the
bounds are ignored. This overall behavior is designed to accommodate the
non–thread-safe Java collection classes such as
java.util.ArrayList and java.util.HashMap. This
behavior is called "conditional containability".
When collections are used to type method parameters or return values, for
example, they can be parameterized with any type formal. But when they are
used to type a field of a containable or thread-safe class, they must be
parameterized with type formals that enable the collection to be containable.
Broadly speaking, the collection classes are written in such a way that they
only use the hashCode(), equals(),
and toString() methods of the objects in the collection. They
do not otherwise utilize the state of the object, that is, the fields of the
objects in the collection are not interesting to the collection, and thus
can be excluded from containability constraints. What does need to prevented,
however, is the state of the objects changing in such a way that might
corrupt the state of the collection. This can be done by requiring
the objects in the collection to be thread-safe, or in many cases
by requiring the above mentioned methods from using the state of the object,
that is, requiring that the object is a reference object.
The non–thread-safe collection classes in
java.util and java.util.concurrent such as
ArrayList, LinkedList, HashSet,
and HashMap have been annotated as @Containable.
Because they are all generic classes, they use conditional containability.
Point is a containable class that uses only
primitively typed fields. Instances of it are in turn contained by the
Rectangle class.
@Containable
public class Point {
private int x;
private int y;
@Unique("return")
@RegionEffects("none")
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Borrowed("this")
@RegionEffects("writes Instance")
public void translate(int dx, int dy) {
x += dx;
y += dy;
}
}
@Containable
public class Rectangle {
@Unique
private final Point topLeft;
@Unique
private final Point bottomRight;
@Unique("return")
public Rectangle(int x1, int y1, int x2, int y2) {
topLeft = new Point(x1, y1);
bottomRight = new Point(x2, y2);
}
@Borrowed("this")
@RegionEffects("writes Instance")
public void translate(int dx, int dy) {
topLeft.translate(dx, dy);
bottomRight.translate(dx, dy);
}
}
The class below shows the use of annotation bounds and conditional containability:
@Containable
class Example<E> {
@Unique
private final List<String> stringList = new ArrayList<String>();
@Unique
private final Set<Object> objSet = new HashSet<Object>();
@Unique
private final Map<String, E> map = new HashMap<String, E>();
@Unique("return")
public Example() {
// ...
}
// ...
}
The type formal E has the annotation bound @ThreadSafe.
The field stringList is containable because the the immutable
type String satisfies the thread-safe bound of
ArrayList allowing the type to be considered
@Containable. Similarly, String and
E satisfy the bounds on the type formals of HashMap
allowing the type to be @Containable, and thus the allowing
the field map to be containable. The field objSet
is not containable, however, because the type HashSet<Object>
is not @Containable, due to Object not
being @ThreadSafe.
This example also demonstrates how the above rules for fields of a
@Containable class may be made less conservative. If
the field is final the declared type of field does not have to
be @Containable (indeed, java.util.List,
java.util.Set, and java.util.Map are not
annotated to be @Containable), as long as the initializer of the field
creates a new instance of a @Containable class.
@annotate tag.
/**
* @annotate Containable
*/
public class Point {
...
}
AnnotationBounds,
ThreadSafe,
NotContainable,
Vouch| Modifier and Type | Optional Element and Description |
|---|---|
boolean |
allowReferenceObject |
boolean |
implementationOnly
Indicates that the implementation of the annotated class should be assured
without making a general statement about the visible behavior of the type
or its subtypes.
|
boolean |
verify
Indicates whether or not tool verification should be attempted.
|
public abstract boolean implementationOnly
true if only the annotated class should be assured without
making a general statement about the visible behavior of the type
or its subtypes, false otherwise. The default value for
this attribute is false.public abstract boolean verify
true if the claim should be verified by a tool, such as
SureLogic JSure, false otherwise. The default value for
this attribute is true.public abstract boolean allowReferenceObject
Copyright © 2012 Surelogic, Inc.. All Rights Reserved.