sealed trait ClassImmutability extends OrderedProperty with ClassImmutabilityPropertyMetaInformation
Specifies the (im)mutability of instances of a specific class. The highest rating is "Immutable", then "Conditionally Immutable", then "Mutable".
An instance of a class is rated as immutable if the state of the object does not change after initialization in a client visible manner! This includes all objects referenced by the instances (transitive hull). However, fields that are lazily initialized (in a thread-safe manner) and which don't change after that do not impede immutability. Conditionally immutable means that the state of the instance of the respective class cannot be mutated, but objects referenced by it can be mutated (so called immutable collections are typically rated as "conditionally immutable"). Mutable means that a client can mutate (directly or indirectly) the state of respective objects. In general the state of a class is determined w.r.t. the declared fields. I.e., an impure method which has, e.g., a call time dependent behavior because it uses the current time, but which does not mutate the state of the class does not affect the mutability rating. The same is true for methods with side-effects related to the state of other types of object.
The mutability assessment is by default done on a per class basis and only directly depends on the super class of the analyzed class. A rating that is based on all actual usages is only meaningful if we analyze an application. E.g., imagine a simple mutable data container class where no field – in the concrete context of a specific application – is ever updated.
Thread-safe Lazily Initialized Fields
A field that is initialized lazily in a thread-safe manner; i.e.,
which is set at most once after construction and which is always set to the
same value independent of the time of (lazy) initialization, may not affect the
mutability rating. However, an analysis may rate such a class as mutable. An
example of such a field is the field that stores the lazily calculated hashCode of
a String object.
Inheritance
- Instances of
java.lang.Objectare immutable. However, if a class defines a constructor which has a parameter of type object and which assigns the respective parameter value to a field will at-most be conditionally immutable (instances of the class object are immutable, but instances of the type (which includes all subtypes) are not immutable; in general we must assume that the referenced object may be (at runtime) some mutable object. - In general, only classes that inherit from (conditionally) immutable class can be (conditionally) immutable; if a class is mutable, all subclasses are also considered to be mutable. I.e., a subclass can never have a higher mutability rating than a superclass.
- All classes for which the superclasstype information is not complete are rated as unknown. (Interfaces are generally ignored as they are always immutable.)
Native Methods
Unknown native methods are considered as mutating the state unless all state is explicitly final; however, this is already handled by the org.opalj.fpcf.analyses.L0FieldMutabilityAnalysis.
Identifying Immutable Objects in Practice
Identifying real world immutable classes as such by means of an analysis is in general a challenging task. For example, to identify the well known immutable class "java.lang.String" as such requires:
- Identifying that the field hash is effectively immutable though the field is only lazily initialized (in a thread-safe manner).
- Determing that all calls to the package-private constructor java.lang.String(byte[] buf, Boolean shared) are actually passed an array that is not shared afterwards. I.e., the ownership is in all cases effectively transfered to the class java.lang.String.
Interfaces
Are not considered during the analysis as they are always immutable. (All fields are (implicitly)
static and final.)
- Alphabetic
- By Inheritance
- ClassImmutability
- ClassImmutabilityPropertyMetaInformation
- OrderedProperty
- Property
- PropertyMetaInformation
- PropertyKind
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
-
final
type
Self = ClassImmutability
- Definition Classes
- ClassImmutabilityPropertyMetaInformation → PropertyMetaInformation
Abstract Value Members
Concrete Value Members
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
final
def
asOrderedProperty: OrderedProperty
- Definition Classes
- Property
-
def
clone(): AnyRef
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @native() @throws( ... )
-
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
finalize(): Unit
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
final
def
id: Int
- Definition Classes
- PropertyMetaInformation → PropertyKind
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
final
def
isOrderedProperty: Boolean
- Definition Classes
- Property
-
final
def
key: PropertyKey[ClassImmutability]
Returns the key used by all
ClassImmutabilityproperties.Returns the key used by all
ClassImmutabilityproperties.- Definition Classes
- ClassImmutability → PropertyMetaInformation
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toString(): String
- Definition Classes
- AnyRef → Any
-
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @throws( ... )