1蚁署、duration 屬性
代碼原型是這樣的:
public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
下面這段代碼是使用 Toast 的示例代碼
//下面是兩個顯示時間的常量
public static final int LENGTH_SHORT = 0;
public static final int LENGTH_LONG = 1;
Toast.makeText(context,"toast message",Toast.LENGTH_SHORT).show();
假如用這種方式編寫:
//直接使用 0 表示 LENGTH_SHORT 可以嗎
Toast.makeText(context,"toast message",0).show();
假如使用 0 來表示 LENGTH_SHORT 的話蹋肮, AS 就直接報錯了炸客,提示信息在截圖中可以看出,顯示這個值必須是 Toast.LENGTH_LONG/LENGTH_SHORT 兩個之一莽鸭。
2荤懂、@Duration的使用
在上面 makeText 中的第三個參數(shù) duration 中添加了一個 @Duration 的東東,就是這個注解約束了duration變量的賦值顶伞。
@IntDef({LENGTH_SHORT, LENGTH_LONG})
@Retention(RetentionPolicy.SOURCE)
public @interface Duration {}
3饵撑、 @IntDef
@IntDef 表示定義該注解 Duration 元素類型為 long 類型剑梳,并且只能取這兩個值,LENGTH_SHORT, LENGTH_LONG滑潘,這兩個值就是 Toast 的常量了垢乙,分別表示0和1。
//該注解標注的信息會保留到編譯時期
@Retention(SOURCE)
//可用于類语卤,接口(包括注解接口)還有枚舉
@Target({ANNOTATION_TYPE})
public @interface IntDef {
/** Defines the allowed constants for this element */
//定義 long 型常量
long[] value() default {};
/** Defines whether the constants can be used as a flag, or just as an enum (the default) */
boolean flag() default false;
}
使用示例
@IntDef({LENGTH_SHORT, LENGTH_LONG})
@Retention(RetentionPolicy.SOURCE)
public @interface Duration {}
4追逮、@StringDef
除了 @IntDef 之外還有 @StringDef ,表示該注解的元素類型為 String 類型粹舵,并且所取的值就在 StringDef 規(guī)定范圍內(nèi)钮孵。在系統(tǒng)提供的 API 中也有體現(xiàn),那就是 Context#getSystemService(@ServiceName @NonNull String name); ServiceName 就是使用 @StringDef 的注解眼滤。
//該注解標注的信息會保留到編譯時期
@Retention(SOURCE)
//可用于類巴席,接口(包括注解接口)還有枚舉
@Target({ANNOTATION_TYPE})
public @interface StringDef {
/** Defines the allowed constants for this element */
String[] value() default {};
}
使用示例
//定義
@Retention(RetentionPolicy.SOURCE)
@StringDef({POWER_SERVICE,WINDOW_SERVICE,LAYOUT_INFLATER_SERVICE})
public @interface ServiceName {
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
}
//使用
public abstract Object getSystemService(@ServiceName String name);
5、使用場景
當某些參數(shù)的值需要是固定的值時诅需,那么就可以使用 @StringDef
或者@IntDef (目前只發(fā)現(xiàn)了這兩種)去標識漾唉,例如系統(tǒng)提供的 Toast 就使用了 @Duration 注解,它是使用 @IntDef 去限制 duration 變量的設(shè)置堰塌,而 Context 中的 getSystemService 中的 name 變量就是使用 @ServiceName 去標識的,該注解就使用使用 @StringDef 去限制 name 的取值赵刑。
我感覺這種做法有點像枚舉的做法。
我們注意到系統(tǒng)提供的這兩個注解的定義:
@Retention(RetentionPolicy.SOURCE)
它們都是用 RetentionPolicy.SOURCE 標識的场刑,它標識該注解的信息不會被編譯般此,會被編譯器拋棄,也就是在編譯前就知道是否發(fā)生了錯誤牵现,既然不會被編譯铐懊,也就無法被加載到 JVM 中了。
@IntDef 和 @StringDef 可以像枚舉一樣在變量的賦值時做一些約束操作施籍,相對比在類中定義一些常量來說居扒,這種方式更加集中同時也實現(xiàn)了類型安全。
6丑慎、使用@String自己定一個 @FlagColor
事先說明,這個 demo 并沒有實際意義瓤摧,只是對模仿 @Duraiton 來寫的一個 demo 而已竿裂。
-
模仿 @Duration 自己定義一個 FlagDemo 類
1.定義需要約束的幾個常量
2.定義注解類FlagColor,使用@StringDef限定上面定義的常量
3.在提供的一些方法使用@FlagColor注解進行傳參和返回值的約束照弥。
public class FlagDemo {
public final static String RED = "red";
public final static String GREEN = "green";
public final static String YELLO = "yello";
private String color;
//定義枚舉
@Retention(RetentionPolicy.RUNTIME)
@StringDef({RED, GREEN, YELLO})
public @interface FlagColor {
}
public String setColor(@FlagColor String color) {
return this.color = color;
}
@FlagColor
public String getColor() {
return color;
}
}
- 測試
注意這里 flagDemo.setColor("") 報錯腻异,報錯結(jié)果跟上面 duration 參數(shù)傳入 0 一樣的,也就是說我們自己定義的 @FlagColor 可以正常使用的这揣。
public static final void main(String[] args) {
FlagDemo flagDemo = new FlagDemo();
//flagDemo.setColor("");
flagDemo.setColor(FlagDemo.GREEN);
System.out.println("color:"+flagDemo.getColor());
}