2010-06-10 45 views
14

Tôi tạo raGán một @Annotation enum một giá trị

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; 
} 

Vì vậy mà tôi hạnh phúc có thể làm một cái gì đó như thế này, đó là hoàn toàn cú pháp pháp lý.

Restrictions r1 = 
    Restrictions.maxLength.setValue(64); 

Lý do là, tôi đang sử dụng enum để hạn chế các loại hạn chế mà có thể được sử dụng, và có thể gán giá trị cho hạn chế đó.

Tuy nhiên, động lực thực tế của tôi là sử dụng hạn chế đó trong @annotation.

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 
public @interface Presentable { 
    Restrictions[] restrictions() default Restrictions.none; 
} 

Vậy đó, tôi có ý định làm điều này:

@Presentable(restrictions=Restrictions.maxLength.setValue(64)) 
public String userName; 

mà, trình biên dịch croaks

The value for annotation enum attribute must be an enum constant expression. 

Có cách nào để đạt được những gì tôi muốn hoàn thành

+1

Có vẻ như bạn đang phát minh lại 'javax.validation' (JSR303). Bạn đã xem xét sử dụng nó chưa? Bạn đã xem API của nó/impls cách họ đã làm nó? Ví dụ. [Hibernate implementation] (http://docs.jboss.org/hibernate/stable/validator/reference/en/html/validator-usingvalidator.html). – BalusC

+0

Hibernate không hoạt động với GAE, phải không? –

+0

là trình duyệt tính hợp lệ ngủ đông, không phải chính là ngủ đông. sẽ hoạt động ở mọi nơi. (bất kỳ nếu nó không, phiên bản dựa trên chú thích của bạn sẽ không phải là phiên bản dựa trên chú thích) –

Trả lời

25

Bạn có thể làm điều đó như thế này:

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(); 
} 
+0

Thật vậy, một cách tiếp cận tốt hơn. Không thể thấy điều này ngay từ đầu, trong khi suy nghĩ dọc theo cùng một dòng. +1 –

2

Bạn có thể đạt được những gì bạn muốn, nhưng không phải với enums trực tiếp.

Nếu bạn thực hiện Hạn chế một lớp học bình thường, với xây dựng tư nhân và các lĩnh vực liên tục tĩnh, sau đó bạn có thể sử dụng phương pháp chaining được kết để tạo ra các trường hợp mới thành thạo:

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); 
    } 
} 

thì nào được sử dụng một cách chính xác như mã ban đầu của bạn:

@Presentable(restrictions=Restrictions.maxLength.setValue(64)) 
public String userName; 

Tuy nhiên, tôi lo ngại vì thiếu OO ở đây - nếu các hạn chế có hành vi hoặc dữ liệu cần thiết khác nhau để định nghĩa thì bạn sẽ kết thúc việc gộp tất cả mọi thứ trong lớp Hạn chế. Sẽ tốt hơn nếu tạo các lớp con cho các loại hạn chế khác nhau.

+0

Bạn không nghĩ rằng bạn đang tạo một cá thể mới trên mọi lời gọi phương thức đã đặt? –

+0

public @interface Có thể giới hạn {Restriction [] limits() mặc định Restriction.none;} kết quả trong trình biên dịch croaking "chỉ các kiểu nguyên thủy, String, Class, chú thích hoặc enum, hoặc 1 mảng mờ của chúng, được cho phép." –

+0

@ h2g2java Đặt 'Restriction' thành một loại chú thích. – mdma

3

Một phần từ lỗi biên dịch, giả sử bạn có thể thực hiện chính xác việc này. Sau đó, bạn không nghĩ rằng việc áp dụng chú thích tương tự trên một số trường khác sẽ làm hỏng chú thích đầu tiên?

Tôi muốn nói,

@Presentable(restrictions=Restrictions.maxLength.setValue(64)) 
public String userName; 
@Presentable(restrictions=Restrictions.maxLength.setValue(32)) 
public String password; 

Các ví dụ tương tự bây giờ sẽ có một giá trị khác nhau, đó là 32. Vì vậy, 64 sẽ bị mất, tôi tin. Trong trường hợp, chúng được xử lý theo thời gian chạy tuần tự, và tại thời điểm chúng ta thay đổi giá trị thành 32, 64 đã được xử lý. Sau đó, tôi giả sử, chúng ta có thể thay đổi phương thức setter trong ví dụ được đưa ra bởi mdma thành một cái gì đó như dưới đây.

static public Restriction setValue(int value) {  
     this.value = value; 
     return this; 
    } 
+0

Chính xác! Enums là các đối tượng liên tục (được biên dịch thành các lớp cuối cùng) sao cho mỗi giá trị enum là một singleton. Enums không bao giờ nên là đối tượng có thể thay đổi được, IMHO. – bennidi

1

tôi đã chọn Abhin như câu trả lời cho câu hỏi của tôi vì nó là toàn diện nhất và nó làm việc khi tôi đã cố gắng nó ra. Tuy nhiên, tôi ghi lại ở đây, dưới hình thức một câu trả lời cho câu hỏi của riêng tôi, những gì tôi thực sự đã làm.

Đổi tên các điều khoản Abhin, đây sẽ là thế nào tôi sẽ áp dụng nó (tương tự như ví dụ Abhin của):

@Presentable({ 
@Restrictions(restriction=Restriction.FractionDigits, value="1"), 
@Restrictions(restriction=Restriction.Length, value="10"), 
    ..... 
}) 

Mà tôi đã quyết định là quá dài dòng. Tôi thậm chí có thể gọi nó là:

@Presentable({ 
@R(r=R.FractionDigits, v="1"), 
@R(r=R.Length, v="10"), 
    ..... 
}) 

Điều này có thể quá khó hiểu và vẫn còn dài dòng. Cái tôi cần là một cái gì đó một lập trình viên có thể chỉ định một cách nhanh chóng và toàn diện:

@Presentable(sequence = 11, maxLen=64, readOnly=true) 

Vì vậy, tôi quyết định sử dụng nhanh chóng và dơ bẩn:

@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; 
} 

Dù sao, tôi đang giữ câu trả lời Abhin trong thầm kín của tôi cho tương lai sử dụng.

Các vấn đề liên quan