前言java
java反射和註解在java裏面很重要,可是不少人對這方面的知識理解不是很好,我來講說我本身對java反射和註解的理解,這兩塊內容原本應該出在一個博客文章裏面講解,可是因爲個人java反射說的內容有點小多,而後我就分開將講解一下。spring
目錄sql
java註解:
比較官方的說法:
從JDK5開始,Java增長對元數據的支持,也就是註解,註解與註釋是有必定區別的,能夠把註解理解爲代碼裏的特殊標記,這些標記能夠在編譯,類加載,運行時被讀取,並執行相應的處理。經過註解開發人員能夠在不改變原有代碼和邏輯的狀況下在源代碼中嵌入補充信息。springboot
註解,能夠看做是對 一個 類/方法 的一個擴展的模版,每一個 類/方法 按照註解類中的規則,來爲 類/方法 註解不一樣的參數,在用到的地方能夠獲得不一樣的 類/方法 中註解的各類參數與值。app
說說個人理解框架
註解就是Annotation,相信很多人也和我以前同樣覺得和註釋同樣,是一段輔助性的文字,其實註解不是這樣的。註解與註釋的區別在於,註解能夠實現程序的某些功能。ide
註解是不會影響java程序的運行,不會干擾程序代碼的運行。通俗來說,註解就像一個標籤,初學者須要知道他就像一個功能標籤,能實現一些功能就好了!入門了再慢慢深刻理解。學習
看下面的例子你就能更好的理解註解了。ui
1.Override
學過java你就知道,你確定見過這種idea
@Override public Object clone() throws CloneNotSupportedException {}
沒錯,@Override就是一個java提供的註解。當你要重寫父類的方法是須要用到這個註解。
2.@Deprecated
這個註解你能看到的時間比較少,可是你應該見過相似的,編譯一個java程序時,編譯器可能會提示你你使用了一個過期的方法(idea會),或者過期的類,過期的成員變量。
3.@SuppressWarnings
這個註解的意思是:阻止編譯器的警告,上一個註解說到@Deprecated會提示你使用過期方法等的一個警告,當你使用了這個註解以後就不會有這種提示了!這個註解須要一個參數,參數都是提早設計好了的。
參數以下
所謂元註解就是註解的註解,雖說這些註解也是java語言提供的,可是他不一樣於上面說的哪幾種註解,上面的幾種註解也是由元註解組成的。他們的源代碼裏面包含了元註解。
元註解有哪些呢?
- @Target:註解的做用目標 - @Retention:註解的生命週期 - @Documented:註解是否應當被包含在 JavaDoc 文檔中 - @Inherited:是否容許子類繼承該註解
這4個值java8以前的元註解,在java8又新增了一個
@Repeatable 元註解,表示被修飾的註解能夠用在同一個聲明式或者類型加上多個相同的註解(包含不一樣的屬性值)
咱們詳細說一下這些註解都是什麼意思
1.@Target 註解的做用目標
具體的做用目標有如下幾個
- ElementType.TYPE:容許被修飾的註解做用在類、接口和枚舉上
- ElementType.FIELD:容許做用在屬性字段上
- ElementType.METHOD:容許做用在方法上
- ElementType.PARAMETER:容許做用在方法參數上
- ElementType.CONSTRUCTOR:容許做用在構造器上
- ElementType.LOCAL_VARIABLE:容許做用在局部變量上
- ElementType.ANNOTATION_TYPE:容許做用在註解上
- ElementType.PACKAGE:容許做用在包上
以上都是這個註解的參數
可能有人會問做用目標是什麼?就是說我聲明的這個註解能夠用在那個地方,好比說@Override,是否是隻能用在重寫的方法上面。若是你學了springboot的話,裏面的不少註解都是可使用在類上面也可使用在方法上面。
2.@Retention 註解的生命週期
什麼意思?註解自己是不會影響正常邏輯程序的運行的,而後這個註解的生命週期指的是我聲明的這個註解會保留到什麼階段,具體的參數以下:
- RetentionPolicy.SOURCE:當前註解編譯期可見,不會寫入 class 文件,會被編譯器丟棄 - RetentionPolicy.CLASS:類加載階段丟棄,會寫入 class 文件,會被java虛擬機丟棄 - RetentionPolicy.RUNTIME:永久保存,能夠反射獲取到對應的註解
3.@Documented 註解是否應當被包含在 JavaDoc 文檔中
這個倒沒有什麼好說的,就是標註被修飾這個註解包含在JavaDoc文檔中。
4.@Inherited 是否容許子類繼承該註解
簡單點說,子類繼承父類時,若是父類的註解有@Inherited標識的註解,子類繼承過來的時候也會自動繼承@Inherited標識的註解。
可是在接口繼承的時候,子類不會繼承任何@Inherited標識的註解。
5.@Repeatable
在須要對同一種註解屢次使用時,每每須要藉助@Repeatable。好比說,如今有一篇文章,這篇文章須要添加多個標籤,這些標籤就至關於註解,可是這個標籤只是內容不一樣,這時候就須要使用到這個註解了。
所謂的其餘註解就是第三方註解,好比說很火的springboot,它提供了不少的註解,能夠替代一些配置文件,告訴這個框架有這個註解是須要提供哪些功能。好比說@Controller,@RequestMapping,@Service等。
講了半天,可能你仍是一臉懵逼,你只講概念,怎麼用?
下面就來介紹這個註解怎麼用,主要是講解註解的聲明用法。
1.註解聲明
public @interface Entity { }
這個和聲明接口很相似,只是在前面多了一個@
具體怎麼用,咱們用一個例子來說解
@Target(ElementType.TYPE)//容許聲明的註解修飾在接口,類,枚舉上面 @Retention(RetentionPolicy.RUNTIME)//代碼運行期間一直保存註解,能夠經過反射獲取 public @interface Entity { //表名,註解的參數,默認爲空 public String tableName() default ""; //中文名稱 public String cnName() default ""; }
解釋一下註解的參數聲明
第一個參數定義參數爲String類型,設置default 默認值,表示這個不是必須的,在使用註解的時候沒有填寫這個參數不會報錯,他會使用默認值。
聲明好註解以後,咱們將這些註解運用到一個實體類上面。
再來一個聲明的做用在屬性上面的註解。
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { //屬性的名稱 public String fieldName() default ""; //屬性的屬性中文名稱 public String fieldCnName() default ""; //屬性的類型 public String Type() default "String"; }
而後咱們將這兩個註解運用到實體類Student上面。
@Entity(tableName = "student",cnName = "學生表") public class Student { @Column(fieldCnName = "姓名",fieldName ="name") private String name; @Column(fieldCnName = "年齡",fieldName = "age",Type = "Integer") private Integer age; @Column(fieldCnName = "性別",fieldName = "sex") private String sex; }
set,get方法沒有貼上來。
具體的用法就是這樣了。而後咱們說說註解與反射的關係,怎麼用反射獲取註解。
不會反射的請看上一篇文章,8000字爲你講懂反射,而後再回來看這篇註解的文章。
上代碼直接
//獲取Class類 Class clazz = Student.class; //獲取類上面的註解 Entity entity = (Entity) clazz.getAnnotation(Entity.class); System.out.println(entity.cnName()+entity.tableName()); //獲取全部該類聲明的屬性 Field fields[] = clazz.getDeclaredFields(); for (Field field:fields){ //獲取對應屬性上面的註解 Column column = field.getAnnotation(Column.class); System.out.println(column.fieldCnName()); }
這個運行結果是
學生表student 姓名 年齡 性別
很簡單是否是。懂了嗎?懂了的話關注走一波?精彩美文天天爲你推送,喜歡手機看文章的還能夠(wx search 全棧學習筆記)!
其實這一部分你懂反射和註解就會了,經過反射和註解你能夠實現一個簡單的萬能的增刪改查。貼個新增的SQL語句代碼吧!
//insert into student_test(student_id,student_name,student_sex) values (1,"Jack","男") StringBuilder sql = new StringBuilder(); Class clazz = object.getClass(); sql.append("insert into "); //獲取類上面的註解 Entity entity = (Entity) clazz.getAnnotation(Entity.class); sql.append(entity.tableName()); sql.append("("); Field[] fields = clazz.getDeclaredFields(); for(Field field:fields){ sql.append(field.getAnnotation(Column.class).fieldName()).append(","); } sql.deleteCharAt(sql.length()-1); sql.append(")"); sql.append(" values ("); for(Field field:fields){ field.setAccessible(true); Object value = field.get(object); if(value.getClass().equals(String.class)){ sql.append("\"").append(value).append("\"").append(","); }else { sql.append(value).append(","); } } sql.deleteCharAt(sql.length()-1); sql.append(")"); System.out.println(sql.toString()); return sql.toString();
結語:以爲文章不錯的,帶上原文連接,歡迎轉發,若是你發現文章中有錯誤能夠評論或者私信我,及時修改!(wx search 全棧學習筆記)精彩美文天天爲你推送!