Implementations of this interface uniquely identify a cached data entry. That means that if two cache keys equal then they compute the same data.
Cache entries are separated into two objects. A Resource, and a Data object. The difference between them that any unmanaged resources (e.g. files, network streams) reside in the Resource, and the Data object is pure data computed based on the Resource. The lifetime of the two objects are managed differently. The Data can be garbage collected at any time, while Resource will be closed when the Data is no longer accessible.
The Data and the Resource objects must never identity equal, and an InvalidCacheKeyImplementationException will be thrown if they do. The Resource must not hold a strong reference to the Data. If it does, the Data will not be garbage collectable.
As a general rule of thumb, the Data and Resource objects should be immutable and hold no state as they can be accessed from multiple agents at the same time. With careful design of the objects, this restriction is not necessary, but recommended.
Implementations can also validate a cache entry, to ensure that always the most up-to-date data is present and recompute it if it's necessary.
When a retrieval is requested from the cache, the cache implementation will check if a cache entry for this key
already exists. If it does, validate(false
, then
the currently allocated resources will be closed, and reallocated using this cache key. If it returns
true
then the current data will be returned. If the data has been already garbage collected, it will be
regenerated using the validated resource.
If no cache entry exists for the retrieval, the allocation and generation will proceed without any validation.
If the cache key implementation throws an error during allocation or generation, the cache entry will be removed completely from the cache, and any open resources will be closed.
The cache implementation uses soft and weak references to keep
track of the generated Datas. When it detects that they have been garbage collected, then the allocated Resource will
be closed sometime in the future via close(
It is possible that the Data is garbage collected, and Resource still resides in the cache. When a new cache entry retrieval is done, it can reuse the still available Resource if possible.
Each cache key can specify an expiry timeout for the generated data. The cache implementation will refer to the generated Data using a SoftReference until the timeout expires, then it will be changed to a WeakReference. The granularity of the expiry timeout checking is implementation dependent.
When a cache entry retrieval is requested, the reference to the returned Data will be refreshed to SoftReference, and the expiry timeout is restarted.
When the cache implementation is closed, all cache entries are closed appropriately.
public Resource | allocate() Allocates the Resource for this cache key. |
public void | close( Closes the objects related to this cache key. |
public boolean | Checks if this cache key identifies the same cache entry and computes the same data as the parameter given the
same circumstances. |
public Data | generate( Generates the Data for this cache key based on a previously allocated Resource. |
public long | Gets the expiry milliseconds of the generated cache Data. |
public int | hashCode() Returns a hash code value for the object. |
public boolean | validate( Validates the cached data if it's still useable. |
The result of the allocation must never be null
.
The allocated Resource can contain unmanaged data which requires explicit closing of the object. (E.g. file
handles, network connections, etc...) Implementations will have an opportunity to close these resources in
close(
If this method throws an exception, the cache entry will be removed for this cache key. Unclosed resources will be closed nonetheless.
null
.Implementations should close unmanaged objects in the allocated Resource.
The Data parameter should not play a role in the closing of the resources, but it is passed to this method
nonetheless. If the Data is no longer accessible, null
is used.
null
if it's no longer available.null
.Indicates whether some other object is "equal to" this one.
The equals
method implements an equivalence relation on non-null object references:
- It is reflexive: for any non-null reference value
x
,x.equals(x)
should returntrue
. - It is symmetric: for any non-null reference values
x
andy
,x.equals(y)
should returntrue
if and only ify.equals(x)
returnstrue
. - It is transitive: for any non-null reference values
x
,y
, andz
, ifx.equals(y)
returnstrue
andy.equals(z)
returnstrue
, thenx.equals(z)
should returntrue
. - It is consistent: for any non-null reference values
x
andy
, multiple invocations ofx.equals(y)
consistently returntrue
or consistently returnfalse
, provided no information used inequals
comparisons on the objects is modified. - For any non-null reference value
x
,x.equals(null)
should returnfalse
.
The equals
method for class Object
implements the most discriminating possible equivalence
relation on objects; that is, for any non-null reference values x
and y
, this method returns
true
if and only if x
and y
refer to the same object (x == y
has the value
true
).
Note that it is generally necessary to override the hashCode
method whenever this method is overridden,
so as to maintain the general contract for the hashCode
method, which states that equal objects must have
equal hash codes.
true
if this object is the same as the obj argument; false
otherwise.
The result of the generation must never be null
. The previously generated Resource must not hold a
strong reference to the returned Data.
The returned Data should not contain any unmanaged data which requires explicit closing of the object. The returned Data might be garbage collected any time in the future when all references are released to it.
If this method throws an exception, the cache entry will be removed for this cache key. Unclosed resources will be closed nonetheless.
After the expiry milliseconds elapse, the cache implementation will convert the soft reference pointing to the generated Data to weak reference. It will result in that the Data will be more easily garbage collected.
If this method returns negative, it will be normalized to 0 (zero).
The general contract of hashCode
is:
- Whenever it is invoked on the same object more than once during an execution of a Java application, the
hashCode
method must consistently return the same integer, provided no information used inequals
comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application. - If two objects are equal according to the
equals(Object)
method, then calling thehashCode
method on each of the two objects must produce the same integer result. - It is not required that if two objects are unequal according to the
Object.equals(
Object) method, then calling thehashCode
method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
As much as is reasonably practical, the hashCode method defined by class Object
does return distinct
integers for distinct objects. (This is typically implemented by converting the internal address of the object
into an integer, but this implementation technique is not required by the Java™ programming language.)
The Data parameter might be null
, if only the Resource is available for validation. Implementations
should handle that gracefully.
null
if it is no longer available.null
.true
if the passed arguments are in a valid state for usage.