註解
1.概述
註解是一種標記,也可以理解成是一種應用在
類、方法、參數、屬性、構造器上的特殊修飾符
2.作用
a.生成文檔,常用的有@param@return等
b.替代配置文件的作用,尤其是在spring等一些框架中,使用註解可以大量的減少配置文件的數量
c.檢查代碼的格式,如@Override,標識某一個方法是否覆蓋了它的父類的方法
3.底層實現原理
註解的底層也是使用反射實現的
註解和接口有點類似,不過申明註解類需要加上@interface
註解類裏面,只支持基本類型、String及枚舉類型
裏面所有屬性被定義成方法,並允許提供默認值
相關類(框架或工具中的類)根據這些信息
來決定如何使用該程序元素或改變它們的行爲
4.註解基本要求
註解是不會影響程序代碼的執行,無論annotation怎麼變化,代碼都始終如一地執行
Java語言解釋器在工作時會忽略這些annotation
因此在JVM中這些annotation是“不起作用”的
只能通過配套的工具才能對這些annontaion類型的信息進行訪問和處理
5.Annotation與interface的異同
a.Annotation類型使用關鍵字@interface而不是interface。繼承了java.lang.annotation.Annotation接口,並非聲明瞭一個interface
b.Annotation類型、方法定義是獨特的、受限制的。Annotation類型的方法必須聲明爲無參數、無異常拋出的。這些方法定義的是annotation的成員:方法名成爲了成員名,而方法返回值成爲了成員的類型
c. 註解方法返回值類型必須爲primitive類型、Class類型、枚舉類型、annotation類型或者由前面類型之一作爲元素的一維數組
d. 方法的後面可以使用default和一個默認數值來聲明成員的默認值,null不能作爲成員默認值,與非annotation類型中定義方法有很大不同
e.Annotation類型和它的方法不能使用annotation類型的參數、成員不能是generic。只有返回值類型是Class的方法可以在annotation類型中使用generic
6.Annotation 分類
a.標準 Annotation
Java 自帶的Annotation,如Override, Deprecated, SuppressWarnings
override標識被標註的方法是否重載了父類的方法,沒有的話則會編譯錯誤
Deprecated代表成員過時,使用的話則編譯器提示
SuppressWarnings告知編譯器關閉對類、成員的警告
b.元 Annotation
專門註解其他註解的註解(警察和督察的關係)
1)@Target — —註解用於什麼地方
TYPE, //給類(型)註解
FIELD, //給字段註解,不要忘了,字段可以是對象
METHOD, //給方法註解
PARAMETER, //給參數註解
CONSTRUCTOR, //給構造方法註解
LOCAL_VARIABLE, //給局部變量註解
ANNOTATION_TYPE,//給註解註解
PACKAGE, //給包註解
2)@Retention — —註解運行狀態
SOURCE, //源碼狀態運行
CLASS, //編譯類文件時運行
RUNTIME //運行時運行
3)@Documented — — 生成說明文檔,添加類的解釋
4)@Inherited — —允許子類繼承父類中的註解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface UserInfo { int id(); String name() default "unknown"; int age(); }
7.使用註解
Tip
Userimport java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Tip { String name() default "unknown"; }
測試類@UserInfo(id = 0, age = 18, name = "張三") public class User { @Tip() private String name; }
package org.xxxx.dmeo; public class Demo01 { public static void main(String[] args) { // 字節碼文件 Class<User> c = User.class; // 獲取 UserInfo info = c.getAnnotation(UserInfo.class); if (info != null) { System.out.println(info.id() + "---" + info.name() + "---" + info.age()); } } }
8.變量上使用註解
測試類
package org.xxxx.dmeo; import java.lang.reflect.Field; public class Demo02 { public static void main(String[] args) throws NoSuchFieldException, SecurityException { // 反射 Class<User> c = User.class; // 獲取屬性 Field f = c.getDeclaredField("name"); Tip tip = f.getAnnotation(Tip.class); if (tip != null) { System.out.println(tip.name()); } } }
9.基於註解的簡單orm映射框架中自動建表實現
JavaBean和數據表結構的對應關係
分析:
類對應表,屬性對應列,對象對應數據庫中表的一條記錄
那麼創建一張表就需要表名,列名,則我們可以分別在類上加上註解
用來得到表名,在屬性上加上註解,得到列名
步驟:
a.定義註解
1)類上的註解:對應於數據庫中的表
2)屬性的註解,對應於數據庫中的列
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 表註釋 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Table { String name(); }
b.應用註解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 字段 @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String name(); // 字段名 String type(); // 字段類型 int len(); // 字段長度 }
c.解析應用
1)建表
@Table(name = "student") // 表名 public class Student { @Column(name = "sid", type = "int", len = 20) private int id; // sid int類型 @Column(name = "sname", type = "varchar", len = 20) private String name; // sname varchar(20) @Column(name = "sage", type = "int", len = 20) private int age; }
2)測試
package org.xxxx.test; import java.lang.reflect.Field; public class Test { public static void main(String[] args) { // 寫語句 StringBuilder sb = new StringBuilder("create table "); // 反射 Class<Student> c = Student.class; // 獲取表註解 Table t = c.getAnnotation(Table.class); if (t != null) { sb.append(t.name() + "("); } else { // 獲取類名 sb.append(c.getSimpleName() + "("); } // 獲取屬性 Field[] fs = c.getDeclaredFields(); for (Field field : fs) { // 獲取字段 Column column = field.getAnnotation(Column.class); // 拼接sql語句 sb.append(column.name() + " ").append(column.type() + "(").append(column.len() + "),"); } // 多拼了一個逗號,截取 sb.deleteCharAt(sb.length() - 1); // 拼最後一個括號 sb.append(""); System.out.println(sb.toString()); } }
d.運行程序