JAVA基礎-註解

想必在項目中大家一定接觸過不少註解,特別是在Spring項目中,那註解的作用是什麼,有何意義?

什麼是註解?

註解可以理解爲一個標籤,這個標籤可以貼在類上,方法上,成員變量上。

註解用來標識某些特徵,類似的可理解爲Interface接口。

public @interface Table {

    String name() default "";
}

元註解

@Retention

Retention 的英文意爲保留期的意思。當 @Retention 應用到一個註解上的時候,它解釋說明了這個註解的的存活時間。
- RetentionPolicy.SOURCE 註解只在源碼階段保留,在編譯器進行編譯時它將被丟棄忽視。
- RetentionPolicy.CLASS 註解只被保留到編譯進行的時候,它並不會被加載到 JVM 中。
- RetentionPolicy.RUNTIME 註解可以保留到程序運行的時候,它會被加載進入到 JVM 中,所以在程序運行時可以獲取到它們。

我們可以這樣的方式來加深理解,@Retention 去給一張標籤解釋的時候,它指定了這張標籤張貼的時間。@Retention 相當於給一張標籤上面蓋了一張時間戳,時間戳指明瞭標籤張貼的時間週期。

@Retention(value = RetentionPolicy.RUNTIME)
public @interface Table {

    String name() default "";
}

 

上面的代碼中,我們指定 Table註解可以在程序運行週期被獲取到,因此它的生命週期非常的長。

@Documented

這個元註解肯定是和文檔有關。它的作用是能夠將註解中的元素包含到 Javadoc 中去。

@Target

Target 是目標的意思,@Target 指定了註解運用的地方。

你可以這樣理解,當一個註解被 @Target 註解時,這個註解就被限定了運用的場景。

類比到標籤,原本標籤是你想張貼到哪個地方就到哪個地方,但是因爲 @Target 的存在,它張貼的地方就非常具體了,比如只能張貼到方法上、類上、方法參數上等等。@Target 有下面的取值

  • ElementType.ANNOTATION_TYPE 可以給一個註解進行註解
  • ElementType.CONSTRUCTOR 可以給構造方法進行註解
  • ElementType.FIELD 可以給屬性進行註解
  • ElementType.LOCAL_VARIABLE 可以給局部變量進行註解
  • ElementType.METHOD 可以給方法進行註解
  • ElementType.PACKAGE 可以給一個包進行註解
  • ElementType.PARAMETER 可以給一個方法內的參數進行註解
  • ElementType.TYPE 可以給一個類型進行註解,比如類、接口、枚舉

@Inherited

Inherited 是繼承的意思,但是它並不是說註解本身可以繼承,而是說如果一個超類被 @Inherited 註解過的註解進行註解的話,那麼如果它的子類沒有被任何註解應用的話,那麼這個子類就繼承了超類的註解。

@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Table {

    String name() default "";

}

@Table
class User{

}

class Member extends User{

}

 

@Repeatable

Repeatable 自然是可重複的意思。@Repeatable 是 Java 1.8 才加進來的,所以算是一個新的特性。

什麼樣的註解會多次應用呢?通常是註解的值可以同時取多個。比如一支筆,可寫可讀

@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Takes {
    Pen[] value() default {};
}


@Repeatable(value = Takes.class)
@interface Pen {
    String method() default "";
}


@Pen(method="write")
@Pen(method="read")
class XiaoMiPen{

}

如何使用註解

接下來我們自定義三個註解,用來模擬數據庫操作

分別是@Table @Column @TableId

@Documented
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Table {

    String name() default "tableName";

}


@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Column {
    String columnName() default "columnName";
}


@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface TableId {
    String Id() default "tableId";
}

創建一個User對象對應User表

package com.test.demo;

@Table(name = "user")
public class User {

    @TableId(Id = "user_id")
    private String userId;

    @Column(columnName = "user_name")
    private String userName;

    @Column(columnName = "age")
    private int age;

    @Column(columnName = "memo")
    private String memo;

    .....getset方法省略

}

利用Java反射我們可以這麼做。此僅爲demo,沒有具體意義

        User user = new User("1","張三",18,"這是個逗比");

        StringBuilder sb = new StringBuilder();

        Class clazz = Class.forName(user.getClass().getName());
        //判斷是不是對應有數據表
        Annotation annotation = clazz.getAnnotation(Table.class);
        if(Objects.isNull(annotation)){
            System.out.println("數據庫沒有這張表");
        }
        Table aClass = (Table) annotation;
        //獲取表名
        String tableName = aClass.name();

        sb.append("select * from ").append(tableName);

        // TODO: 2020/6/29 excuteSql
        System.out.println(sb.toString());


        //獲取主鍵
        String id = "";
        for (Field declaredField : clazz.getDeclaredFields()) {
            TableId column = declaredField.getAnnotation(TableId.class);
            if(!Objects.isNull(column) ){
                id = column.Id();
                System.out.println(id);
                declaredField.setAccessible(true);
                //查詢
                sb.append(" where "+id +"=" + declaredField.get(user));
                System.out.println(sb);
            }
        }



        //獲取其他字段
        for (Field declaredField : clazz.getDeclaredFields()) {
            Column column = declaredField.getAnnotation(Column.class);
            if(!Objects.isNull(column) ){
                String name = column.columnName();
                System.out.println(name);
            }
        }

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章