java 之 注解
注解就像javadoc的注釋一樣,只不過注釋是靜態源碼級別的,而注解可以使運行時的,不但可以告訴編譯器某些事,也可以用來減少工作負擔。
下面為三種標準注解以及四種元注解:
1、@Target 表示該注解用于什么地方,可能的 ElemenetType 參數包括:
ElemenetType.CONSTRUCTOR 構造器聲明
ElemenetType.FIELD 域聲明(包括 enum 實例)
ElemenetType.LOCAL_VARIABLE 局部變量聲明
ElemenetType.METHOD 方法聲明
ElemenetType.PACKAGE 包聲明
ElemenetType.PARAMETER 參數聲明
ElemenetType.TYPE 類,接口(包括注解類型)或enum聲明
2、@Retention 表示在什么級別保存該注解信息。可選的 RetentionPolicy 參數包括:
RetentionPolicy.SOURCE 注解將被編譯器丟棄
RetentionPolicy.CLASS 注解在class文件中可用,但會被VM丟棄
RetentionPolicy.RUNTIME VM將在運行期也保留注釋,因此可以通過反射機制讀取注解的信息
3、@Documented 將此注解包含在 javadoc 中
4、@Inherited 允許子類繼承父類中的注解'
5、@Deprecated 表示當前元素是不贊成使用的。
6、@Override 表示當前方法是覆蓋父類的方法
7、@SuppressWarnings 表示關閉一些不當的編譯器警告信息
下面看示例,《thinking in java 4th》中[1070]示例改的:
2 import java.lang.annotation.ElementType;
3 import java.lang.annotation.Retention;
4 import java.lang.annotation.RetentionPolicy;
5 import java.lang.annotation.Target;
6 import java.lang.reflect.Field;
7 import java.util.ArrayList;
8 import java.util.List;
9
10
11 public class Test {
12
13 @Target(ElementType.TYPE)
14 @Retention(RetentionPolicy.RUNTIME)
15 public @interface DBTable{
16 public String name() default "";
17 }
18
19 //定義SQL約束注解
20 @Target(ElementType.FIELD)//這個注解用于字段
21 @Retention(RetentionPolicy.RUNTIME)//這個注解保留到運行時
22 public @interface Constraints{
23 boolean primaryKey() default false;
24 boolean allowNull() default true;
25 boolean unique() default false;
26 }
27
28 //定義SQLString 類型注解
29 @Target(ElementType.FIELD)
30 @Retention(RetentionPolicy.RUNTIME)
31 public @interface SQLString{
32 int value() default 0;
33 String name() default "";
34 Constraints constraints() default @Constraints; //這是個嵌套注解,默認值就是@約束注解
35 }
36
37 //定義SQLInterger類型注解
38 @Target(ElementType.FIELD)
39 @Retention(RetentionPolicy.RUNTIME)
40 public @interface SQLInterger{
41 String name() default "";
42 Constraints constraints() default @Constraints;
43 }
44
45 public @interface Uniqueness{
46 Constraints constraints() default @Constraints(unique=true); //嵌套了Consttrains注解,默認使注解的unique元素為t
47 }
48
49
50
51 //我們擴展一下,自定義SQLDate注解
52 @Target(ElementType.FIELD)
53 @Retention(RetentionPolicy.RUNTIME)
54 public @interface SQLDate{
55 String name() default "2012-01-01"; //注解只允許那幾中基本數據類型
56 Constraints constraints() default @Constraints;
57 }
58
59 //這是一個java bean,包含了要往數據庫寫入得一個對象的所有信息
60 @DBTable(name="MEMBER")
61 public class Member{
62 @SQLString(30)//為firstName注解, @SQLString ,value是30,其他為默認,firstName
63 String firstName;
64 @SQLString(50)//同上,value其實是個快捷方式,如果注釋只定義了value這個元素,那么賦值的時候,可以用鍵值對那樣賦值
65 String lastName;
66 @SQLInterger Integer age;//同上,這里注解的所有字段為默認,名字為age
67 //這是個內嵌元素的注解
68 @SQLString(value=30,constraints=@Constraints(primaryKey=true))
69 String handle;
70 @SQLString(value=30,name="2020-10-1")
71 String birthDay;
72
73 public String getFirstName() {
74 return firstName;
75 }
76
77 public String getLastName() {
78 return lastName;
79 }
80
81 public Integer getAge() {
82 return age;
83 }
84
85 public String getBirthDay() {
86 return birthDay;
87 }
88
89 int memberCount;
90
91 public String toString(){
92 return handle;
93 }
94
95 }
96
97
98 public static void main(String[] args) throws ClassNotFoundException{
99 String className = "Test$Member";
100 Class<?> cl=Class.forName(className); //反射,獲得類的class字節碼
101 //反射出cl的注解,參數是DBTable的字節碼class
102 DBTable dbTable=cl.getAnnotation(DBTable.class);
103 String tableName=dbTable.name();
104 //這個用來存儲java beans的屬性
105 List<String> columnDefs=new ArrayList<String>();
106 //獲取這個java beans的所有屬性,這里也順便學到java bean相關的反射
107 for(Field field:cl.getDeclaredFields()){
108 String columnName=null;
109 //獲取這個java bean屬性的所有注解
110 Annotation[] anns=field.getDeclaredAnnotations();
111 if(anns.length<1)
112 continue; //如果沒有注解,則跳過,到下一個屬性
113 //如果注解集合的第一元素是個SQLInterger注解的話
114 if(anns[0] instanceof SQLInterger){
115 SQLInterger sInt=(SQLInterger)anns[0];
116 if(sInt.name().length()<1)
117 //如果注解元素name沒有定義名稱的話,則使用屬性名作為名字
118 columnName=field.getName().toUpperCase();
119 else
120 //定義了的話,就用定義的東西
121 columnName=sInt.name();
122 columnDefs.add(columnName+" INT"+getConstraints(sInt.constraints()));
123 }
124 //如果第一個元素是SQLString注解的話
125 if(anns[0] instanceof SQLString ){
126 SQLString sString=(SQLString) anns[0];
127 if(sString.name().length()<1)
128 columnName=field.getName().toUpperCase();
129 else
130 columnName=sString.name();
131 columnDefs.add(columnName+" VARCHAR("+sString.value()+")"+getConstraints(sString.constraints()));
132 }
133 }
134
135 //下面模擬創建表
136 StringBuilder createCommand=new StringBuilder("CREATE TABLE "+tableName+"(");
137 for(String columnDef:columnDefs)
138 createCommand.append("\n "+columnDef+".");
139 String tableCreate=createCommand.substring(0,createCommand.length()-1)+");";
140 System.out.println("Table Cration SQL for "+className+" is:\n"+tableCreate);
141
142 }
143
144 //獲得約束
145 private static String getConstraints(Constraints con){
146 String constraints="";
147 if(!con.allowNull()) //如果約束不允許使用空值
148 constraints +=" NOT NULL";
149 if(con.primaryKey())//如果是主鍵
150 constraints+=" PRIMARY KEY";
151 if(con.unique())
152 constraints+=" UNIQUE";
153 return constraints;
154 }
155
156
157 }
浙公網安備 33010602011771號