Java基礎(chǔ)--注解

[TOC]

概念

注解(Annotation)為我們在代碼中添加信息提供了一種形式化的方法,使我們可以在稍后某個時刻非常方便地使用這些數(shù)據(jù)

每當創(chuàng)建描述符性質(zhì)的類和接口時,一旦其中包含了重復(fù)性的工作,就可以考慮使用注解來簡化與自動化該過程。
注解可用來進行一些提示性、安全檢查的作用(如標記注解,@Override等),也可用來在運行時進行邏輯上的操作,簡化模板式代碼的創(chuàng)建,使代碼更加簡潔,編寫更加高效。注解常見于各種框架當中,學(xué)會注解可以對框架理解的更加深入。

注解的類型

注解的分類

按來源可以分為JDK自帶注解、第三方框架注解、自定義注解。
JDK自帶注解

注解名稱 功能
@Override 表示當前的方法定義將覆蓋超類中的方法
@Deprecated 使用了這個注解, 表示不建議使用
@SuppressWarnings 關(guān)閉不當?shù)木幾g器警告(JDK>=1.5)

按聲明周期可以分為源碼注解、編譯時注解、運行時注解(下述祥)

元注解

元注解是用來注解其他注解的注解

注解名稱 功能
@Target 表示該注解可以用于什么地方
@Retention 需要在什么級別保存該注解信息
@Documented 將此注解包含在Javadoc中
@Inherited 允許子類繼承(extends)父類中的注解

@Target的參數(shù)ElementType包括以下幾種:

ElementType類型 解釋
CONSTRUCTOR 構(gòu)造器的聲明
FIELD 域聲明,包括enum實例(即,字段)
LOCAL_VARIABLE 局部變量聲明
METHOD 方法聲明
PACKAGE 包聲明
PARAMETER 參數(shù)聲明
TYPE 類、接口(包括注解類型)或enum聲明

@Retention可選的RetentionPolicy參數(shù)包括:

RetentionPolicy 解釋
SOURCE 注解將被編譯器丟棄
CLASS 注解在class文件中可用,但會被VM丟棄(注解在源碼和class文件中存在)
RUNTIME VM將在運行期間也保留注解,因此可以通過反射機制讀取注解的信息

自定義注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
    int id();
    String description() default "no description"
}

public class PasswordUtils {
    @UseCase(id = 47, description = "must contain at least one numeric")
    public void validatePassword(String password) {
        // TODO: 2016/12/21  
    }
}

注解可用的元素類型如下:所有基本類型(int,float等),String,Class,enum,Annotation,以上類型的數(shù)組
如果注解只有一個類型一般用value()命名,用value()命名的時候,使用注解不需要以價值對的形式給出值

注解解釋器

使用Java的反射機制編寫注解解釋器讀取注解的信息。
實例如下需求如下:使用注解創(chuàng)建數(shù)據(jù)庫查詢的過濾器。

// Table.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}

// Column.java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}

// Filter.java
@Table("users")
public class Filter {

    @Column("name")
    private String name;

    @Column("email")
    private String email;

    @Column("phone")
    private String phone;

    @Column("age")
    private int age;

    @Column("sex")
    private int sex;

    public String getName() {
        return name;
    }
    // 省略了其余的getter和setter方法
}

// Test.java
public class Test {

    public static void main(String[] args) {
        Filter f1 = new Filter();
        f1.setName("Akis");
        f1.setAge(22);

        Filter f2 = new Filter();
        f2.setName("xcc");
        f2.setSex(1);
        f2.setPhone("******");

        String sql1 = query(f1);
        String sql2 = query(f2);

        System.out.println(sql1);
        System.out.println(sql2);
    }


    public static String query(Filter filter) {
        StringBuilder sb = new StringBuilder();
        sb.append("SELECT * FROM ");

        Class c = filter.getClass();
        Table table = (Table) c.getAnnotation(Table.class);
        String tableName = table.value();
        sb.append(tableName).append(" WHERE 1 = 1");

        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            Column column = field.getDeclaredAnnotation(Column.class);
            String columnName = column.value();
            String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
            Object columnValue = null;
            try {
                Method method = c.getDeclaredMethod(methodName);
                columnValue = method.invoke(filter);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (columnValue instanceof String) {
                sb.append(" AND ").append(columnName).append("=").append("'").append(columnValue).append("'");
            } else if (columnValue instanceof Integer && (Integer)columnValue != 0) {
                sb.append(" AND ").append(columnName).append("=").append(columnValue);
            }
        }
        sb.append(";");
        return sb.toString();
    }
}

// output
SELECT * FROM users WHERE 1 = 1 AND name='Akis' AND age=22;
SELECT * FROM users WHERE 1 = 1 AND name='xcc' AND phone='******' AND sex=1;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文章涉及代碼已放到github上annotation-study 1.Annotation為何而來 What:A...
    zlcook閱讀 29,730評論 15 116
  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一種元程序中的元素關(guān)聯(lián)任何信息和...
    九尾喵的薛定諤閱讀 3,393評論 0 2
  • 對著星空大聲喊, 你走了真好, 不然我總會擔(dān)心你要走,分別之后; 我瞞著多有人,繼續(xù)愛了你很久很久; 可惜我只是你...
    四月芳華閱讀 328評論 0 0
  • 2008年秋天,我從青島某大學(xué)畢業(yè),雖然連續(xù)迎接了考研失敗和山東公務(wù)員省考的失利,但是由于我對深入社會到處找工作始...
    沙竹叢中閱讀 635評論 5 11
  • 一樹威,一林美,一曲蜿蜒小溪水。 南為水,北山背,四通曲折成經(jīng)緯。 蟲兒飛,狗兒追,馬蹄蹬雀踐花蕊。 云盤山,天空...
    潔汝大弟閱讀 305評論 0 12

友情鏈接更多精彩內(nèi)容