1. 注解
什么注解?
注解:annotation(標識,標簽),從Java5開始支持注解
注解能干什么?
注解是貼在java程序元素上面
程序元素 : 類,方法,字段,方法參數,接口,構造函數,枚舉
注解貼在程序上面有什么用?
在反射的時候,動態可以獲取字節碼,方法,字段等等程序元素,獲取了這些程序元素,那么就能獲取程序元素上貼的注解。這些注解會參與程序運行提供比較的相關信息和數據
枚舉是一個特殊類
注解是一個特殊的接口,所有的注解都繼承自java.lang.annotation這個接口。
完整的注解(從編寫到最終運行)需要三方面的參與。
1.需要定義一個注解。
2.需要一個被貼的程序元素(類,方法,字段,構造器等)
3.第三方程序的支持(賦予我注解的特殊功能)
1.1. JDK中內置的注解
1.@Override 限定覆寫父類方法 2.@Deprecated 標記已過時的成員,被標記的方法不推薦使用. 問題1:有的注解可以貼在類上,方法上,字段上,有的卻只能貼在類上 問題2:有的注解可以有一個或者多個參數,有的卻不行。 |
1.2. JDK中的元注解
注解: 貼在程序元素上面的標簽
元注解 : 注解的注解(貼在注解上面的注解)
元注解 主要用於限定當前的注解能夠貼在哪兒?能夠保留在哪個階段(程序執行三個階段
源代碼階段,字節碼階段,JVM中)
@Retention: 表示注解可以保存在哪一個時期.
保存的時期的值,封裝在RetentionPolicy枚舉類中
枚舉常量摘要 |
CLASS |
注解保留到字節碼階段,運行時候失效了 |
RUNTIME |
注解保留到運行階段,運行時候使用反射獲取做相應的程序處理-一般開發者自定注解都保留運行階段 |
SOURCE |
注解在源代碼階段有效,編譯字節碼就失效了 |
|
@Target: 表示注解可以貼在哪些位置(類,方法上,構造器上等等).
位置的常量封裝在ElementType枚舉類中:
ElementType.ANNOTATION_TYPE只能修飾Annotation
ElementType.CONSTRUCTOR只能修飾構造方法
ElementType.FIELD只能修飾字段(屬性),包括枚舉常量
ElementType.LOCAL_VARIABLE只能修飾局部變量
ElementType.METHOD只能修飾方法
ElementType.PACKAGE只能修飾包(極少使用)
ElementType.PARAMETER只能修飾參數
ElementType.TYPE只能修飾類,接口,枚舉
1.3. 自定義注解
1. 定義一個注解
語法 : 注解關鍵字 @Interface
2. 被貼的程序元素
3. 第三方程序參與賦予注解功能(反射程序)
程序代碼
package cn.zj.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 設置注解的元注解
* 1,Target
* 注解可以貼在那些程序元素上面
* 2, Retention
* 注解可以保留到那個階段,一般自定義保留到RUNTIME運行時
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
/**
* 注解屬性
* 語法
* 數據類型 屬性名稱();
* 如果屬性名稱是 value ,在使用注解的時候,可以省略 value
*/
//String value();
String name();
} |
package cn.zj.annotation;
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 value();
} |
package cn.zj.pojo;
import cn.zj.annotation.Column;
import cn.zj.annotation.Table;
/**
* @Table 注解的作用就是為了解決在反射時候,實體類和 表明不匹配
* 實體類 :User --> user 理論上對應數據表 user
* 實際上數據庫表名 :t_user
* 這樣如果默認不匹配 反射時候對不上,反射封裝存儲數據就失敗
*/
@Table(name="t_user")
public class User {
private Integer id;
@Column("username")
private String name;
private String password;
private String email;
private String phone;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
public String getPhone() {
return phone;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
'}';
}
} |
測試代碼
package cn.zj.test;
import cn.zj.annotation.Column;
import cn.zj.annotation.Table;
import cn.zj.pojo.User;
import java.lang.reflect.Field;
public class AnnotationTest {
//使用反射獲取字節碼,並獲取對應元素的注解
public static void main(String[] args) {
//1.獲取User類的字節碼實例
Class<User> clz = User.class;
//2.判斷類上面是否有 @Table注解
boolean flag = clz.isAnnotationPresent(Table.class);
if(flag){
//1.獲取@Table注解
Table table = clz.getAnnotation(Table.class);
System.out.println(table);
//2.獲取具體的屬性值
String tableName = table.name();
System.out.println(tableName);
}
//2.獲取所有字段
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
//1.判斷字段上是否有注解
if(field.isAnnotationPresent(Column.class)){
//2.獲取字段上的注解
Column column = field.getAnnotation(Column.class);
System.out.println(column);
}
}
}
} |