我创建了
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;
}
所以我很乐意做这样的事情,这是完全合法的语法。
Restrictions r1 =
Restrictions.maxLength.setValue(64);
原因是,我使用enum 来限制可以使用的限制类型,并且能够为该限制分配值。
但是,我的实际动机是在@annotation中使用该限制。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Presentable {
Restrictions[] restrictions() default Restrictions.none;
}
所以,我打算这样做:
@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;
,编译器呱呱叫
The value for annotation enum attribute must be an enum constant expression.
有没有办法完成我想要完成的任务
答案 0 :(得分:26)
你可以这样做:
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();
}
答案 1 :(得分:3)
编译错误的一部分,假设你能够做到这一点。那么你不觉得在其他领域应用类似的注释会破坏第一个吗?
我的意思是说,
@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;
@Presentable(restrictions=Restrictions.maxLength.setValue(32))
public String password;
相同的实例现在将具有不同的值,即32。因此,我相信64将会丢失。如果它们在运行时顺序处理,并且在我们将值更改为32时,已经处理了64个。然后我想,我们可以将setter
给出的示例中的mdma
方法更改为如下所示。
static public Restriction setValue(int value) {
this.value = value;
return this;
}
答案 2 :(得分:2)
你可以实现你想要的,但不能直接使用枚举。
如果使用私有构造函数和静态常量字段使限制成为常规类,则可以使用方法链来流畅地创建新实例:
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);
}
}
然后将其用作原始代码:
@Presentable(restrictions=Restrictions.maxLength.setValue(64))
public String userName;
但是,我担心这里缺少OO - 如果限制具有不同的行为或定义所需的数据,那么最终会将所有内容都集中在Restrictions类中。最好为不同的限制类型创建子类。
答案 3 :(得分:1)
我选择Abhin作为我问题的答案,因为它是最全面的,当我试用它时它起作用了。但是,我在这里以对自己问题的回答的形式记录了我实际做了什么。
重命名Abhin的术语,这就是我应用它的方式(类似于Abhin的例子):
@Presentable({
@Restrictions(restriction=Restriction.FractionDigits, value="1"),
@Restrictions(restriction=Restriction.Length, value="10"),
.....
})
我决定过于冗长。我甚至可以把它简化为:
@Presentable({
@R(r=R.FractionDigits, v="1"),
@R(r=R.Length, v="10"),
.....
})
这可能太难以理解而且仍然冗长。我需要的是程序员可以快速全面地指定的东西:
@Presentable(sequence = 11, maxLen=64, readOnly=true)
因此,我决定使用快速而肮脏的东西:
@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;
}
无论如何,我将Abhin的答案保留在我的凹槽中以备将来使用。