Java 为 @Annotation 枚举赋值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3010993/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Assigning an @Annotation enum a value
提问by Blessed Geek
I created
我创建
enum Restrictions{
none,
enumeration,
fractionDigits,
length,
maxExclusive,
maxInclusive,
maxLength,
minExclusive,
minInclusive,
minLength,
pattern,
totalDigits,
whiteSpace;
public Restrictions setValue(int value){
this.value = value;
return this;
}
public int value;
}
So that I could happily do something like this, which is perfectly legal syntax.
这样我就可以愉快地做这样的事情,这是完全合法的语法。
Restrictions r1 =
Restrictions.maxLength.setValue(64);
The reason being is, I am using enum to restrict the type of restriction that could be used, and be able to assign a value to that restriction.
原因是,我使用 enum来限制可以使用的限制类型,并且能够为该限制分配一个值。
However, my actual motivation is to use that restriction in an @annotation.
但是,我的实际动机是在 @annotation 中使用该限制。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Presentable {
Restrictions[] restrictions() default Restrictions.none;
}
So that, I intended to do this:
所以,我打算这样做:
@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;
to which, the compiler croaks
对此,编译器发出嘶嘶声
The value for annotation enum attribute must be an enum constant expression.
Is there a way to accomplish what I wish to accomplish
有没有办法完成我希望完成的事情
采纳答案by Abhinav Sarkar
You can do it like this:
你可以这样做:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
class Person {
@Presentable({
@Restriction(type = RestrictionType.LENGTH, value = 5),
@Restriction(type = RestrictionType.FRACTION_DIGIT, value = 2)
})
public String name;
}
enum RestrictionType {
NONE, LENGTH, FRACTION_DIGIT;
}
@Retention(RetentionPolicy.RUNTIME)
@interface Restriction {
//The below fixes the compile error by changing type from String to RestrictionType
RestrictionType type() default RestrictionType.NONE;
int value() default 0;
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@interface Presentable {
Restriction[] value();
}
回答by mdma
You can achieve what you want, but not with enums directly.
您可以实现您想要的,但不能直接使用枚举。
If you make Restriction a regular class, with private constructor and static constant fields, you can then use method chaining to create new instances fluently:
如果您将 Restriction 设为具有私有构造函数和静态常量字段的常规类,则可以使用方法链流畅地创建新实例:
enum RestrictionType
{
none,
enumeration,
maximumLength,
// ... etc.
}
class Restriction {
static public final Restriction none = new Restriction(RestrictionType.none);
static public final Restriction enumeration = new Restriction(RestrictionType.enumeration);
static public final Restriction maximumLength = new Restriction(RestrictionType.maximumLength);
... etc
RestrictionType type;
int value;
private Restriction(RestrictionType type)
{
this(type, 0);
}
private Restriction(RestrictionType type, int value)
{
this.type = type;
this.value = value; // you don't really need
}
static public Restriction setValue(int value)
{
return new Restriction(type, value);
}
}
Which is then used exactly as your original code:
然后完全按照您的原始代码使用:
@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;
However, I'm concerned for the lack of OO here - if the restrictions have different behaviour or data needed for definition, then you will end up lumping everything in the Restrictions class. It will be better to create subclasses for the different restriction types.
但是,我担心这里缺少 OO - 如果限制具有不同的行为或定义所需的数据,那么您最终会将所有内容归入 Restrictions 类。最好为不同的限制类型创建子类。
回答by Adeel Ansari
A part from compilation error, suppose you are able to do exactly this. Then don't you think applying the similar annotation on some other field will ruin the first one?
编译错误的一部分,假设您能够做到这一点。那么你不认为在其他领域应用类似的注释会破坏第一个吗?
I mean to say,
我的意思是说,
@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;
@Presentable(restrictions=Restrictions.maxLength.setValue(32))
public String password;
The same instance will now have a different value, that is 32. So, the 64 will be lost, I believe. In case, they are processed on runtime sequentially, and at the time we change the value to 32, 64 one has already been processed. Then I suppose, we can change the setter
method in the example given by mdma
to something like below.
同一个实例现在将具有不同的值,即 32。因此,我相信 64 将丢失。如果它们在运行时按顺序处理,当我们将值更改为 32 时,64 已经被处理了。然后我想,我们可以将setter
给出的示例中的方法更改为mdma
如下所示。
static public Restriction setValue(int value) {
this.value = value;
return this;
}
回答by Blessed Geek
I chose Abhin's as the answer to my question because it was the most comprehensive and it worked when I tried it out. However, I document here, in the form of an answer to my own question, what I actually did.
我选择 Abhin's 作为我的问题的答案,因为它是最全面的,并且在我尝试时很有效。但是,我在这里以对我自己问题的回答的形式记录了我实际做了什么。
Renaming Abhin's terms, this would be how I would apply it (similar to Abhin's example):
重命名 Abhin 的术语,这将是我将如何应用它(类似于 Abhin 的示例):
@Presentable({
@Restrictions(restriction=Restriction.FractionDigits, value="1"),
@Restrictions(restriction=Restriction.Length, value="10"),
.....
})
Which I decided is too verbose. I could even abridge it to:
我的决定太冗长了。我什至可以将其简化为:
@Presentable({
@R(r=R.FractionDigits, v="1"),
@R(r=R.Length, v="10"),
.....
})
Which might be too incomprehensible and still to verbose. What I needed was something a programmer could specify quickly and comprehensively:
这可能太难以理解了,而且仍然冗长。我需要的是程序员可以快速而全面地指定的东西:
@Presentable(sequence = 11, maxLen=64, readOnly=true)
Therefore, I decided to use the quick and dirty:
因此,我决定使用快速而肮脏的:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Presentable {
int sequence();
String caption() default "";
int fractionDigits() default -1;
int length() default -1;
int maxLen() default -1;
int minLen() default -1;
int totalDigits() default -1;
float maxVal() default -1;
float minVal() default -1;
String pattern() default "";
String whiteSpace() default "";
boolean readOnly() default false;
boolean multiValue() default false;
boolean hidden() default false;
boolean isTest() default true;
}
Anyway, I am keeping Abhin's answer in my recesses for future use.
无论如何,我将 Abhin 的答案保留在我的休息处以备将来使用。