Java註解與反射的使用
Java註解的使用
學前須知
具有Java基礎知識,包括JVM類載入,反射等基礎。
反射是框架的前提,通過註解和反射機制,java實現了動態語言的一部分特性
元註解
Java 定義了一套註解,共有 7 個,3 個在 java.lang 中,剩下 4 個在 java.lang.annotation 中。
java.lang 中的註解
@Override - 檢查該方法是否是重寫方法。如果發現其父類,或者是引用的介面中並沒有該方法時,會報編譯錯誤。
@Deprecated - 標記過時方法。如果使用該方法,會報編譯警告。有這個註解的方法不建議使用
@SuppressWarnings - 指示編譯器去忽略註解中宣告的警告。去除告警波浪線,專治強迫症。
java.lang.annotation中的註解
@Target - 註解使用的範圍,比如包,類,方法,欄位
@Retention - 表示需要在什麼級別儲存該註釋資訊,用於描述註解的生命週期(一般都是RUNTIME級別)
@Documented - 標記這些註解是否包含在javadoc中
@Inherited - 說明子類可以繼承父類的註解
// 使用註解
@MyAnnotation
public class Test01 {
}
// 定義一個註解
// 註解可以用在哪些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})
// 註解在什麼地方有效,一般是Runtime
@Retention(value = RetentionPolicy.RUNTIME)
// 將註解生成在JavaDoc中
@Documented
// 子類繼承父類註解
@Inherited
// 定義一個註解
@interface MyAnnotation{
}
註解的定義和傳參
// 無預設值的註解
@MyAnnotation2(name = "qwer")
public class Test02 {
}
// 引數預設為value,且有預設值的註解
@MyAnnotation3
class Test02_2 {
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
// 預設值名是value
String value() default "";
// 定義變數後面要加()
String name();
// 可以給變數賦預設值
int age() default 18;
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
// 預設值名是value
String value() default "預設值";
}
反射
Reflection (反射)是Java被視為動態語言的關鍵,反射機制允許程式在執行期藉助於Reflection API取得任何類的內部資訊,並能直接操作任意物件的內部屬性及方法
載入完類之後,在堆記憶體的方法區中就產生了一個Class型別的物件(一 個類只有
一個Class物件), 這個物件就包含了完整的類的結構資訊。我們可以通過這個對
象看到類的結構。這個物件就像一面鏡子, 透過這個鏡子看到類的結構,所以,
我們形象的稱之為:反射
五種獲取Class物件的方法
反射的使用
public class Test03 {
public static void main(String[] args) throws Exception{
Class c1 = Class.forName("Test");
Method methods[] = c1.getMethods();
System.out.println("獲取到method[0]方法名 "+methods[0].getName());
// 注意!,獲取類的方法順序與類定義方法的順序不一定一致 多次執行結果會有所不同
// 通過反射,呼叫空參方法和有參方法
methods[0].invoke(new Test(),null);
methods[1].invoke(new Test(),"aaa"); //String.Class
System.out.println("============================");
Class c2 = Class.forName("Person");
Method method1 = c2.getMethod("setName",String.class);
// 類載入的理解,我set引數李四,最後打出來還是張三,參考圖片理解
method1.invoke(new Person(),"李四");
Method method2 = c2.getMethod("getName",null);
System.out.println(method2.invoke(new Person()));
// 獲取欄位
Field f1 = c2.getDeclaredField("name");
Field f2[] = c2.getFields();//獲取許可權為public的引數
Field f3[] = c2.getDeclaredFields();//獲取所有的引數
System.out.println(f1);
System.out.println("============================");
for (int i = 0; i < f3.length ; i++) {
System.out.println(f3[i]);
}
}
}
class Test{
public void fun1(){
System.out.println("method f1 running");
}
public void fun2(String str){
System.out.println("method f1 running args:"+str);
}
}
class Person{
public String name = "張三";
private int age = 18;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
參考圖片
反射建立物件
public class Test04 {
public static void main(String[] args) throws Exception{
Class c1 = Class.forName("User");
// 無參的構造器,構造方法
Constructor constructor1 = c1.getConstructor();
User user1 = (User)constructor1.newInstance();
System.out.println(user1.toString());
// 有參的構造器,構造方法
Constructor constructor2 = c1.getConstructor(String.class,String.class);
//constructor2.setAccessible(true);//關閉許可權檢查,提升效能
User user2 = (User)constructor2.newInstance("張三","123456");
System.out.println(user2.toString());
}
}
class User{
public String username;
public String password;
public String getUsername() {
return username;
}
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
反射操作註解
public class Test05 {
public static void main(String[] args) throws Exception{
Class c1 = Class.forName("MyUser");
Annotation annotations[] = c1.getAnnotations();
TableUser userAnno = (TableUser) c1.getAnnotation(TableUser.class);
String value = userAnno.value();
System.out.printf(value);
// 獲得類指定的註解
Field id = c1.getDeclaredField("id");
FieldUser fieldAnno = (FieldUser) id.getAnnotation(FieldUser.class);
String columName = fieldAnno.columName();
String type = fieldAnno.type();
int length = fieldAnno.length();
System.out.printf("%s %s %d",columName,type,length);
}
}
@TableUser("user")
class MyUser{
@FieldUser(columName = "db_id",type = "varchar",length = 64)
public String id;
@FieldUser(columName = "db_age",type = "number",length = 3)
public int age;
}
// 類的註解
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@interface TableUser{
String value();
}
// 屬性的註解
@Target(value = {ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface FieldUser{
String columName();
String type();
int length();
}
練習
註解運算元據庫示例
效果如圖
專案地址:
https://github.com/13884566853/annotation-test
補充
從 Java 7 開始,額外新增了 3 個註解:
@SafeVarargs - Java 7 開始支援,忽略任何使用引數為泛型變數的方法或建構函式呼叫產生的警告。
@FunctionalInterface - Java 8 開始支援,標識一個匿名函式或函式式介面。
@Repeatable - Java 8 開始支援,標識某註解可以在同一個宣告上使用多次。
相關文章
- Java反射與註解Java反射
- Java之註解與反射Java反射
- Java註解與反射機制Java反射
- Java反射-註解Java反射
- java註解,反射Java反射
- 註解與反射反射
- Java註解與反射學習筆記Java反射筆記
- Java 註解和反射Java反射
- Java註解和反射Java反射
- 小白都能學會的Java註解與反射機制Java反射
- JAVA-註解(2)-自定義註解及反射註解Java反射
- 【Java基礎】反射和註解Java反射
- 【譯】8. Java反射——註解Java反射
- Java反射和註解基本用法Java反射
- Java反射動態修改註解的值Java反射
- 03-Java核心類庫_列舉、註解與反射Java反射
- Java ”框架 = 註解 + 反射 + 設計模式“ 之 註解詳解Java框架反射設計模式
- Java列舉類、註解和反射Java反射
- 註解 & 反射反射
- java註解與反射(非常詳細, 帶有很多樣例)Java反射
- java註解基礎與使用Java
- 【進階】Spring中的註解與反射Spring反射
- 註解和反射反射
- Java註解的使用Java
- 反射、註解與依賴注入總結反射依賴注入
- 【轉】java中註解的使用與例項Java
- Java利用spring註解做反射機制JavaSpring反射
- JAVA面試 基礎加強與鞏固:反射、註解、泛型等Java面試反射泛型
- 好程式設計師Java培訓分享註解與反射原理說明程式設計師Java反射
- 從Java反射機制到Android註解框架Java反射Android框架
- Java反射與反射優化Java反射優化
- Java註解知識梳理與簡單使用Java
- 自定義註解以及註解在反射中的應用反射
- 關於Java中泛型、反射和註解的掃盲篇Java泛型反射
- Java基礎加強筆記——測試、反射、註解Java筆記反射
- 【Android】註解框架(一) 基礎知識Java 反射Android框架Java反射
- 自定義註解+反射 實現給註解新增功能的效果反射
- myBatis——註解,#{}與${},resultMap的使用MyBatis