"Cashing"-Annotation...
Hi,
I've written this piece of code:
private (static) AdministrationUnitConfigurations configuration;
public (static) AdministrationUnitConfigurations getConfigs() {
if ( configuration == null ) {
configuration = doInitializeIt...();
}
return configuration;
}
I think others may have those constructs in their classes too. Now I
would like to have an annotation like "@Cache" or something else.
Whith this annotation I could "bind" the private field to the method:
Rearranger could modify its sorting algorithm, so that this field is
always directly above the method
Some warnings can be showed, that warn me about direct access to the
field...
What do u think about it? Any comments?
Johannes Schneider
请先登录再写评论。
Basically what you're looking for is something like static local variables in C/C++, yes? I'd probably explore inner-class-based solutions first, rather than annotations. I don't have a pattern immediately in mind, but I'm sure something can be pounded into place. If you do go the annotation-route, I'd suggest something like @StaticLocal(methodName), rather than @Cache. Computer languages work better if you name things for their essence, rather than their use. Promotes clarity of thought, and prevents unwarranted assumptions.
--Dave Griffith
Well,
I don't knwo C/C++. But I think "static local" exacly describes what I
mean...
The inner-class-approach seems to be the overkill...
Johannes Schneider
Dave Griffith wrote:
The analogy to "static local" variables breaks if the variable isn't static.
Maybe a better name would be "@FullyEncapsulated", meaning all access is through getter/setters only.
In general I think this feature is a little too obscure to warant inclusion into Idea core, though.
But even without the annotation, it there could be an option to relayout code, so that fields are placed in front of their getters.
Johannes Schneider wrote:
In case of static variable, this code could safely be rewritten as:
private static AdministrationUnitConfigurations configuration =
doInitializeIt();
public (static) AdministrationUnitConfigurations getConfigs() {
return configuration;
}
as the JLS says that a static field initializers should be executed on
the first field access and not at class loading time.
Still, the cached annotation could be useful for the non-static case. On
the other hand, I rarely use this pattern as it leads to a lot of
problems, unless your classes are immutable. Also, in the common case,
you should consider the threading issues.
On the naming, I think that local-static would only confuse the
developers who do not have C background. I think that 'cached' or
'retained' would be much better. Like this:
public toString() {
@Cached String s = ; return s; } which after post-processing would generate the following code: public toString() { synchronized(__cached$toString$lock) { if (__cached$toString$s==null) { __cached$toString$s = ]]>;
}
}
return __cached$toString$s;
}
If we have to take this model further, we have to include invalidation
groups, like:
public toArray() {
@Cached("array-representation") Object[] o = ...;
return o;
}
Invalidate("array-representation") public add(Object) {....}
Invalidate("array-representation") public remove(Object) {....}
and so on.
And this is still not a complete solution, since you can modify the
contained objects by referencing them directly.
Now, as I think of it, I'd really like a 'const' in the Java 6.0 :)
Not quite true. All fields will be initialized on the first access to any field:
In this case initBar() will be called. If acces were routed through a getter it would not, of course.
Isn't this the lazy initialization pattern? How about @LazyInit?
Ideally something like aspect oriented programming could be used to make sure the field initialization method is called before it is accessed...
--
Hans Häggström
I think of more than "only" lazy initialization.
There could also exist a method that "invalidates" the cache (setting
the field to null)...
Johannes Schneider
� wrote:
By the way.
How about a "cache" refactoring?
Before :
public Foo getFoo() {
return ; } After : protected Foo cachedFoo; public Foo getFoo() { if (cachedFoo == null) { cachedFoo = ]]>;
}
return cachedFoo;
}
Dave Griffith wrote:
+1
Or how about this scenario:
Select someExpression and invoke cached variable refactoring / intention:
It's doing a bit more, and requires the user to enter
a name for the property (although the name of the variable
we are assigning someExpression to could be used as a
suggestion if present), but in my experience this
corresponds better to the typical use case.
--
Hans Häggström