註解(元數據)爲咱們在代碼中添加信息提供了一種形式化的方法,使咱們能夠在以後的某一個時刻很是方便地使用這些數據。 ---《Java編程思想》java
其實註解能夠理解爲一個工具類,只要使用了這個工具類後,主體類將會添加一些功能,就好像一個法師身邊多了一個小精靈。註解在必定程度上是把元數據和源代碼文件結合在一塊兒,而不是保存在外部文檔中這一個大的趨勢所催生的,不用去配置xml文件,不用去修改一些變量。之因此這麼說註解,有註解自己特性所決定的,只要在類、方法、變量等代碼的上方或者前方添加某個註解,那麼咱們將有這個註解的某個功能。數據庫
不得不說,註解是Java SE5重要語言之一,能夠用來提供完整地描述程序所需的信息,存儲程序的額外有關的信息。註解能夠用來生成描述符文件,甚至或是新的類定義,有助於減輕編寫「樣板」代碼的負擔。編程
1、經常使用的Java內置的註解app
1 @Deprecated 2 public static void sayHello(){ 3 System.out.println("Hello!!!"); 4 }
1 @SuppressWarnings(value = { "deprecation" }) 2 public static void main(String[] args) { 3 System.runFinalizersOnExit(true); 4 5 }
2、定義註解框架
除了咱們使用Java自己擁有的註解以外,咱們更多要本身去定義註解,以知足各類個性化的需求。在不少框架,Spring,Mybatis中,註解是被使用很是頻繁地一個Java工具。常見@Controller,@Component,@Service,@ResponseBody等等。下面就來看看這個定義中有方法和做用。ide
定義註解重要有兩個元註解,@Target和@Retention,一個是註解做用的目標對象(FIELD,METHOD,CONSTRUCTOR),一個是註解做用的保持的一個生命週期(SOURCE,CLASS,RUNTIME),java源文件--》class文件--》內存中字節碼。工具
例子一,用於密碼的校驗測試
1 package annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Target(ElementType.METHOD) 9 @Retention(RetentionPolicy.RUNTIME) 10 public @interface UseCase { 11 12 public int id(); 13 public String description() default "no description"; 14 }
1 package annotation; 2 3 import java.util.List; 4 5 public class PasswordUtils { 6 7 @UseCase(id =47 ,description = "passwords must contain at lease one numeric") 8 public boolean validatePassword(String password){ 9 return (password.matches("\\w*\\d\\w*")); 10 } 11 12 @UseCase(id =48) 13 public String encryptPassword(String password){ 14 return new StringBuilder(password).reverse().toString(); 15 } 16 17 @UseCase(id = 49,description = "New password can't equel previously used ones") 18 public boolean checkForNewPassword(List<String> prevPasswords, String password){ 19 return !prevPasswords.contains(password); 20 } 21 }
1 package annotation; 2 3 import java.lang.reflect.Method; 4 import java.util.ArrayList; 5 import java.util.Collections; 6 import java.util.List; 7 8 public class UseCaseTracker { 9 10 public static void trackUseCases(List<Integer> useCases, Class<?> cl){ 11 for(Method m : cl.getDeclaredMethods()){ 12 UseCase uc = m.getAnnotation(UseCase.class); 13 if(uc != null){ 14 System.out.println("Found Use Case:" + uc.id() + " " + uc.description()); 15 useCases.remove(new Integer(uc.id())); 16 } 17 } 18 for(int i :useCases){ 19 System.out.println("Warning : Missing use Case -" + i); 20 } 21 } 22 23 public static void main(String[] args) { 24 List<Integer> useCases = new ArrayList<Integer>(); 25 Collections.addAll(useCases, 47,48,49,50); 26 trackUseCases(useCases,PasswordUtils.class); 27 } 28 }
Found Use Case:47 passwords must contain at lease one numeric Found Use Case:48 no description Found Use Case:49 New password can't equel previously used ones Warning : Missing use Case -50
下面咱們將進行一個定義註解在《Java編程思想》的一個很好的例子。目的是根據註解去生成一個SQL語句,這也是十分有用的。ui
1 package annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Target(ElementType.TYPE) 9 @Retention(RetentionPolicy.RUNTIME) 10 public @interface DBTable { 11 12 public String name() default ""; 13 }
1 package annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Target(ElementType.FIELD) 9 @Retention(RetentionPolicy.RUNTIME) 10 public @interface Constraints { 11 12 boolean primaryKey() default false; 13 boolean allowNull() default true; 14 boolean unique() default false; 15 }
1 package annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Target(ElementType.FIELD) 9 @Retention(RetentionPolicy.RUNTIME) 10 public @interface SQLString { 11 12 int value() default 0; 13 String name() default ""; 14 Constraints constraints() default @Constraints; 15 }
1 package annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Target(ElementType.FIELD) 9 @Retention(RetentionPolicy.RUNTIME) 10 public @interface SQLInteger { 11 12 String name() default ""; 13 Constraints constraints() default @Constraints; 14 }
package annotation; @DBTable(name ="MEMBER") public class Member { @SQLString(30) String firstName; @SQLString(50) String lastName; @SQLInteger Integer age; @SQLString(value =30, constraints = @Constraints(primaryKey = true)) String handle; static int memberCount; public String getHandle(){return handle;} public String getFirstName(){return firstName;} public String getlastName(){return lastName;} public String toString(){return handle;} public Integer getAge(){return age;} }
1 package annotation; 2 3 import java.lang.annotation.Annotation; 4 import java.lang.reflect.Field; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 public class TableCreator { 9 10 public static void main(String[] args) throws Exception { 11 getSQL(new String[]{"annotation.Member"}); 12 } 13 14 public static void getSQL(String[] args) throws ClassNotFoundException { 15 if(args.length <1){ 16 System.out.println("arguments : annotated classes"); 17 System.exit(0); 18 } 19 for(String className :args){ 20 Class<?> cl = Class.forName(className); 21 DBTable dbTable = cl.getAnnotation(DBTable.class); 22 if(dbTable == null){ 23 System.out.println("No DBTable annotation in class " + className); 24 continue; 25 } 26 String tableName = dbTable.name(); 27 //If the name is empty ,use the Class name; 28 if(tableName.length() <1){ 29 tableName = cl.getName().toUpperCase(); 30 } 31 List<String> columnDefs = new ArrayList<String>(); 32 for(Field field : cl.getDeclaredFields()){ 33 String columnName = null; 34 Annotation[] anns = field.getDeclaredAnnotations(); 35 if(anns.length <1){ 36 continue;//not a db table column 37 } 38 if(anns[0] instanceof SQLInteger){ 39 SQLInteger sInt = (SQLInteger) anns[0]; 40 //user field name if name not specified 41 if(sInt.name().length() < 1) 42 columnName = field.getName().toUpperCase(); 43 else 44 columnName= sInt.name(); 45 columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints())); 46 } 47 if(anns[0] instanceof SQLString){ 48 SQLString sString = (SQLString) anns[0]; 49 //use field name if name not specified 50 if(sString.name().length() <1){ 51 columnName = field.getName().toUpperCase(); 52 }else{ 53 columnName = sString.name(); 54 } 55 columnDefs.add(columnName + " VARCHAR(" +sString.value() + ")" 56 +getConstraints(sString.constraints())); 57 } 58 StringBuilder createCommand = new StringBuilder( 59 "CREATE TABLE " + tableName +"("); 60 for(String columnDef : columnDefs) 61 createCommand.append("\n " + columnDef + ","); 62 //Remove trailing comma 63 String tableCreate = createCommand.substring(0,createCommand.length() -1) +");"; 64 System.out.println("Table Creation SQL for " + className + " is :\n" + tableCreate);; 65 } 66 67 } 68 } 69 70 private static String getConstraints(Constraints con) { 71 // TODO Auto-generated method stub 72 String constraints = ""; 73 if(!con.allowNull()) 74 constraints += "NOT NULL"; 75 if(con.primaryKey()) 76 constraints += "PRIMARY KEY"; 77 if(con.unique()) 78 constraints += "UNIQUE"; 79 return constraints; 80 } 81 }
Table Creation SQL for annotation.Member is : CREATE TABLE MEMBER( FIRSTNAME VARCHAR(30)); Table Creation SQL for annotation.Member is : CREATE TABLE MEMBER( FIRSTNAME VARCHAR(30), LASTNAME VARCHAR(50)); Table Creation SQL for annotation.Member is : CREATE TABLE MEMBER( FIRSTNAME VARCHAR(30), LASTNAME VARCHAR(50), AGE INT); Table Creation SQL for annotation.Member is : CREATE TABLE MEMBER( FIRSTNAME VARCHAR(30), LASTNAME VARCHAR(50), AGE INT, HANDLE VARCHAR(30)PRIMARY KEY);
3、現階段中不少在運用到註解的例子spa