Java Annotation Overloading?
In my project, I have defined the an开发者_运维百科 annotation similar to the following:
(Omitting@Retention
, @Target
for brevity)
public @interface DecaysTo {
String[] value();
}
Since originally writing it, our needs have changed and I have now defined an enum that I want to be able to use in place of the string:
public enum Particle {
ELECTRON,
ANTIELECTRON,
NEUTRINO,
ANTINEUTRINO,
...
}
To avoid updating every instance of this annotation, I would like to be able to construct the annotation with either a String
or a member of enum Particle
without having to update every instance of this annotation to specify the attribute. However, since we define the annotation's attributes, and not constructors, it seems impossible to overload it.
// In a perfect world, either of these would work ...
public @interface DecaysTo {
String[] value();
Particle[] value();
}
@DecaysTo({"Electron", ...})
@DecaysTo({Particle.ELECTRON, ...})
// without having to explicitly specify which attribute to set:
public @interface DecaysTo {
String[] stringVals();
Particle[] enumVals();
}
@DecaysTo(stringVals = {"Electron", ...})
@DecaysTo(enumVals = {Particle.ELECTRON, ...})
Also attempted:
public @interface DecaysTo {
Object[] value();
}
Is there any way to do this that doesn't involve going back through and editing an enormous amount of code?
The best way is to find and replace all previous annotations. You don't want old design lingering around. Keep a clean code base throughout refactorings.
Suppose you don't want to do that, or you don't own the code that use the annotation, you should keep two annotation types. in your annotation processing code, you look for both, and if the old one is used, convert it to the new one.
DecaysToV2 anno = getAnnotation( DecaysToV2.class );
if(anno = null)
{
DecaysTo anno_old = getAnnotation( DecaysTo.class );
if(anno_old!=null)
anno = convert (anno_old);
}
DecaysToV2 is just an interface which you can impl:
DecaysToV2 convert( DecaysTo old )
{
DecaysToV2Impl impl = new DecaysToV2Impl();
impl.value = ...
return impl;
}
static class DecaysToV2Impl implements DecaysToV2
{
Particle[] value;
public Particle[] value(){ return this.value; }
}
You could just deprecate this annotation and introduce a new one (say @DecaysToParticle) for new code.
Maybe what you really need is
enum Particle {
ELECTRON("Electron"),
...
private String name;
private Particle(String name) {
this.name = name;
}
public String getName() {return name;}
}
(You could also generate the name with string functions, but this apporach is more flexible).
Also I dont understand what enormous amount of code have to be changed, since (I guess) your suggestions would not compile, I hope thats not what your code actually looks like.
精彩评论