Getting an instance of an annotation with default element values
Right,
I have defined an annotation like so:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ParallelConfiguration {
public int numThreads() default 3;
}
Elsewhere in my code, i do something like this:
Class someClass;
ParallelConfiguration conf = someClass.getAnnotation(ParallelConfiguration.class);
int numThreads = conf.numThreads();
Obviously, if someClass lacks a ParallelConfiguration, this won't work. At
present, my code actually does:
Class someClass;
ParallelConfiguration conf = someClass.getAnnotation(ParallelConfiguration.class);
int numThreads;
if (conf != null) numThreads = conf.numThreads();
else numThreads = DEFAULT_NUMBER_OF_THREADS;
But this is really stupid. I already have a default for numThreads
defined, in the ParallelConfiguration annotation itself; defining another
default elsewhere is dreadful. I could refactor a little bit to make both
bits of code refer to the same constant:
public @interface ParallelConfiguration {
public static final int DEFAULT_NUM_THREADS = 3;
public int numThreads() default DEFAULT_NUM_THREADS;
}
if (conf != null) numThreads = conf.numThreads();
else numThreads = ParallelConfiguration.DEFAULT_NUM_THREADS;
And that's better, but it's still stupid: it's not making use of the fact
that the annotation has a natural way of expressing defaults. This comes
back to haunt me when i start to add more things to the annotation:
public @interface ParallelConfiguration {
public static final int DEFAULT_NUM_THREADS = 3;
public static final String DEFAULT_THREAD_NAME_PREFIX = "worker";
public int numThreads() default DEFAULT_NUM_THREADS;
public String threadNamePrefix() default DEFAULT_THREAD_NAME_PREFIX;
public int threadPriority() default Thread.NORM_PRIORITY;
}
When my client code starts to look really vile:
int numThreads;
String threadNamePrefix;
int threadPriority;
if (conf != null) {
numThreads = conf.numThreads();
threadNamePrefix = conf.threadNamePrefic();
threadPriority = conf.threadPriority();
}
else {
// all this just duplicates the default definitions!
numThreads = ParallelConfiguration.DEFAULT_NUM_THREADS;
threadNamePrefix = ParallelConfiguration.DEFAULT_THREAD_NAME_PREFIX;
threadPriority = Thread.NORM_PRIORITY;
}
What i really want to do is something like this:
if (conf == null) conf = getDefaultInstance(ParallelConfiguration.class);
int numThreads = conf.numThreads();
String threadNamePrefix = conf.threadNamePrefic();
int threadPriority = conf.threadPriority();
The problem is that i have no idea how to do the getDefaultInstance bit.
Is there a standard way to do this?
The best i've come up with is to apply some sort of trickery, like this:
public @interface ParallelConfiguration {
@ParallelConfiguration
public static class DefaultBearer {}
public static final ParallelConfiguration DEFAULT = DefaultBearer.class.getAnnotation(ParallelConfiguration.class);
public int numThreads() default 3;
}
Which works (well, compiles, and looks like it should work), and does what
i want, but is pure evil. I could get rid of the DefaultBearer class by
applying the annotation to itself, but that doesn't exactly reduce the
level of evil!
Any thoughts?
tom
--
Can we fix it? Yes we can!