最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java 注解的基礎(chǔ)詳細(xì)介紹

 更新時(shí)間:2017年09月06日 14:41:23   投稿:lqh  
這篇文章主要介紹了java 注解的基礎(chǔ)詳細(xì)介紹的相關(guān)資料,希望通過本文大家能掌握注解的使用方法,需要的朋友可以參考下

java 注解的基礎(chǔ)詳細(xì)介紹

前言

注解是Java引入的一項(xiàng)非常受歡迎的補(bǔ)充,它提供了一種結(jié)構(gòu)化的,并且具有類型檢查能力的新途徑,從而使得程序員能夠?yàn)榇a加入元數(shù)據(jù),而不會(huì)導(dǎo)致代碼雜亂且難以閱讀。使用注解能夠幫助我們避免編寫累贅的部署描述文件,以及其他生成的文件。

注解的語法比較簡單,除了@符號的使用之外,它基本與java固有的語法一致。但由于java源碼中提供的內(nèi)置注解很少,所以大部分同學(xué)對注解都不是很了解,雖然我們都接觸過,比如java內(nèi)置的幾種注解:

 @Override,表示當(dāng)前的方法定義將覆蓋超類中的方法。
  @Deprecated,表示當(dāng)前方法即將廢棄,不推薦使用。
  @SuppressWarnings,表示忽略編譯器的警告信息。

但這并不能讓我們體會(huì)到注解的強(qiáng)大和便利,其實(shí)Java還另外提供了四種注解,專門負(fù)責(zé)新注解的創(chuàng)建。今天我們就來學(xué)習(xí)下怎么創(chuàng)建和使用注解。

注解類的定義

首先看看一個(gè)注解類的定義:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
  boolean primaryKey() default false;
  boolean allowNull() default true;
  boolean unique() default false;
}

除了@符號以外,注解類的定義很像一個(gè)空的接口。定義注解時(shí),會(huì)需要一些元注解,如@Target和@Retention,java提供了四種元注解,定義如下:

@Target:表示該注解可以用于什么地方。

取值(ElementType)包括:
CONSTRUCTOR:用于描述構(gòu)造器
FIELD:用于描述域
LOCAL_VARIABLE:用于描述局部變量
METHOD:用于描述方法
PACKAGE:用于描述包
PARAMETER:用于描述參數(shù)
TYPE:用于描述類、接口(包括注解類型) 或enum聲明

@Retention:表示需要在什么級別保存該注解信息。

取值(RetentionPolicy)包括:
SOURCE:在源文件中有效(即源文件保留)
CLASS:在class文件中有效(即class保留)
RUNTIME:在運(yùn)行時(shí)有效(即運(yùn)行時(shí)保留),因此可以通過反射機(jī)制讀取注解的信息。

@Documented:表示將此注解包含在javadoc中。

@Inherited:表示允許子類繼承父類中的注解。

可以看出 定義注解格式為:
  public @interface 注解名 {定義體}

注解類中定義的元素稱為注解元素,注解元素可用的類型如下:

 所有基本數(shù)據(jù)類型(int,float,boolean,byte,double,char,long,short)
 String類型
 Class類型
 enum類型
 Annotation類型
 以上所有類型的數(shù)組

如果你使用了其它類型,那編譯器就會(huì)報(bào)錯(cuò)。注意,也不允許使用任何包裝類型,但由于自動(dòng)打包的存在,這算不上什么限制。注解也可以作為元素的類型,比如我們再定義一個(gè)注解類:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
  int value() default 0;
  String name() default "";
  Constraints constraints() default @Constraints;
  //@Constraints后沒有括號表明使用默認(rèn)值,可以加括號,在里面定義初始值,比如@Constraints(unique=true)
}

可以看出,所有的注解元素都有一個(gè)默認(rèn)值。編譯器對元素的默認(rèn)值有些過分挑剔,首先,元素必須具有默認(rèn)值;其次不能以null作為默認(rèn)值。所以我們只能自己定義一些特殊的值,例如空字符串或負(fù)數(shù),來表示某個(gè)元素不存在。

注解類的使用

注解類定義好了,怎么使用呢?

為了體現(xiàn)注解的便利和強(qiáng)大,在這里我們寫一個(gè)demo,使用注解來自動(dòng)生成一個(gè)建數(shù)據(jù)庫表的SQL命令。

另外我們再提供兩個(gè)注解類:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
  public String name() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
  String name() default "";
  Constraints constraints() default @Constraints;
}

好,現(xiàn)在我們一共有4個(gè)注解類。

@DBTable 代表數(shù)據(jù)庫表,注解元素name表示表名;
@Constraints 代表對數(shù)據(jù)表每一列的條件補(bǔ)充,有primaryKey是不是主鍵,默認(rèn)false,allowNull是否允許為空,默認(rèn)true,unique數(shù)據(jù)是否唯一,默認(rèn)false;
@SQLString 代表表中的String列,注解元素value表示列長度,name表示列名,constraints表示對列的一些約束條件;
@SQLInteger 代表表中的int列,name表示列名,constraints表示對列的一些約束條件;

下面我們定義一個(gè)簡單的Bean類,在其中應(yīng)用以上4個(gè)注解類:

@DBTable(name = "MEMBER")
public class Member {
  @SQLString(30) String firstName;
  @SQLString(50) String lastName;
  @SQLInteger int age;
  @SQLString(value = 30, constraints = @Constraints(primaryKey = true)) String handle;
  public String getFirstName() {
    return firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public int getAge() {
    return age;
  }
  public String getHandle() {
    return handle;
  }
  public String toString() {
    return handle;
  }
}

注解的元素在使用時(shí)表現(xiàn)為名-值對的形式,并需要置于 @注解類名 聲明之后的括號內(nèi)。如果沒有使用括號,代表全部使用默認(rèn)值。

1、類的注解@DBTable給定了值MEMBER,它將會(huì)用來作為表的名字;

2、Bean的屬性firstName和lastName,都被注解為@SQLString類型,這些注解有兩個(gè)有趣的地方:第一,他們都使用了嵌入的@Constraints注解的默認(rèn)值;第二,它們都使用了快捷方式。何謂快捷方式?如果程序員的注解中定義了名為value的元素,并且在應(yīng)用該注解的時(shí)候,如果該元素是唯一需要賦值的一個(gè)元素,那么此時(shí)無需使用名-值對的這種語法,而只需在括號內(nèi)給出value元素所需的值即可。這可以應(yīng)用于任何合法類型的元素。當(dāng)然了,這也限制了程序員必須將此元素命名為value。
Bean屬性age全部使用默認(rèn)值,handle為主鍵。

3、Bean屬性age全部使用默認(rèn)值,handle為主鍵。

實(shí)現(xiàn)注解處理器

注解類使用上了,我們還需要一個(gè)注解處理器來解析我們定義的Bean,這樣才能將注解轉(zhuǎn)換成我們需要的操作。

以下定義解析Bean的注解處理器,我們的目的是要輸出一條SQL語句。主要用到了反射技術(shù)。

public class TableCreator {
  public static void main(String[] args) throws Exception{
//傳入我們定義好的Bean類名,帶上包名    
Class<?> cl = Class.forName("annotation.Member");
//檢查我們傳入的類是否帶有@DBTable注解
    DBTable dbTable = cl.getAnnotation(DBTable.class);
    List<String> columnDefs = new ArrayList<String>();
//得到類中的所有定義的屬性
    for(Field filed : cl.getDeclaredFields()){
      String columnName = null;
//得到屬性的注解,對一個(gè)目標(biāo)可以使用多個(gè)注解
      Annotation[] anns = filed.getAnnotations();
      if(anns.length < 1){
        continue;
      }
//SQLString注解走著
      if(anns[0] instanceof SQLString){
        SQLString sString = (SQLString)anns[0];
//name()使用的是默認(rèn)值,所以這里取屬性名
        if(sString.name().length() < 1){
          columnName = filed.getName().toUpperCase();
        }else{
          columnName = sString.name();
        }
//構(gòu)建SQL語句
        columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints()));
      }
//SQLInteger注解走著
      if(anns[0] instanceof SQLInteger){
        SQLInteger sInt = (SQLInteger)anns[0];
        if(sInt.name().length() < 1){
          columnName = filed.getName().toUpperCase();
        }else{
          columnName = sInt.name();
        }
        columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints()));
      }
    }
    StringBuilder creator = new StringBuilder("CREATE TABLE " + dbTable.name() + "( ");
    for(String c : columnDefs){
      creator.append("\n" + c + ",");
    }
    creator.deleteCharAt(creator.length()-1);
    creator.append(")");
    System.out.println(creator.toString());
  }

  private static String getConstraints(Constraints con) {
    String constraints = "";
    if(!con.allowNull()){
      constraints += " NOT NULL";
    }
    if(con.primaryKey()){
      constraints += " PRIMARY KEY";
    }
    if(con.unique()){
      constraints += " UNIQUE";
    }
    return constraints;
  }
}

最后的輸出:

CREATE TABLE MEMBER( 
FIRSTNAME VARCHAR(30), 
LASTNAME VARCHAR(50), 
AGE INT, 
HANDLE VARCHAR(30) PRIMARY KEY)

總結(jié)

最后,通過這篇文章,我們要學(xué)到一下幾點(diǎn):

1、了解Java 4種元注解的說明與使用;
2、會(huì)自定義注解類;
3、了解注解元素的定義和規(guī)則;
4、會(huì)使用注解類;
5、能寫一個(gè)簡單的注解處理器解析注解。

如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • SpringBoot Application注解原理及代碼詳解

    SpringBoot Application注解原理及代碼詳解

    這篇文章主要介紹了SpringBoot Application注解原理及代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • java實(shí)現(xiàn)Dijkstra最短路徑算法

    java實(shí)現(xiàn)Dijkstra最短路徑算法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)Dijkstra最短路徑算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • SpringBoot使用thymeleaf實(shí)現(xiàn)前端表格

    SpringBoot使用thymeleaf實(shí)現(xiàn)前端表格

    雖然現(xiàn)在流行前后端分離,但是后端模版在一些關(guān)鍵地方還是非常有用的,例如郵件模版、代碼模版等。當(dāng)然也不排除一些古老的項(xiàng)目后端依然使用動(dòng)態(tài)模版。Thymeleaf 簡潔漂亮、容易理解,并且完美支持 HTML5,可以直接打開靜態(tài)頁面,同時(shí)不新增標(biāo)簽,只需增強(qiáng)屬性
    2022-10-10
  • Java中comparator接口和Comparable接口的比較解析

    Java中comparator接口和Comparable接口的比較解析

    這篇文章主要介紹了Java中comparator接口和Comparable接口的比較解析,Java提供了一個(gè)用于比較的接口Comparator和Comparable接口,提供了一個(gè)比較的方法,所有實(shí)現(xiàn)該接口的類,都動(dòng)態(tài)的實(shí)現(xiàn)了該比較方法,需要的朋友可以參考下
    2023-08-08
  • 淺析java修飾符訪問權(quán)限(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)

    淺析java修飾符訪問權(quán)限(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)

    Java有四種訪問權(quán)限,其中三種有訪問權(quán)限修飾符,分別為private,public和protected,還有一種不帶任何修飾符,下面通過本文給大家簡單介紹下java修飾符訪問權(quán)限相關(guān)知識,感興趣的朋友一起學(xué)習(xí)吧
    2017-04-04
  • 淺析Java中String與StringBuffer拼接的區(qū)別

    淺析Java中String與StringBuffer拼接的區(qū)別

    String拼接會(huì)創(chuàng)建一個(gè)新的String對象,存儲(chǔ)拼接后的字符串,StringBuffer拼接是直接在本身拼接,會(huì)即時(shí)刷新。下面通過本文給大家介紹Java中String與StringBuffer拼接的區(qū)別,感興趣的朋友一起看看吧
    2017-06-06
  • java?poi之XWPFDocument如何讀取word內(nèi)容并創(chuàng)建新的word

    java?poi之XWPFDocument如何讀取word內(nèi)容并創(chuàng)建新的word

    這篇文章主要介紹了java?poi之XWPFDocument如何讀取word內(nèi)容并創(chuàng)建新的word問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Java 高并發(fā)九:鎖的優(yōu)化和注意事項(xiàng)詳解

    Java 高并發(fā)九:鎖的優(yōu)化和注意事項(xiàng)詳解

    本文主要介紹Java高并發(fā)鎖的優(yōu)化和注意事項(xiàng),這里整理了詳細(xì)的資料,并講解了 1. 鎖優(yōu)化的思路和方法 2. 虛擬機(jī)內(nèi)的鎖優(yōu)化 3. 一個(gè)錯(cuò)誤使用鎖的案例 4. ThreadLocal及其源碼分析等知識,有需要的小伙伴可以參考下
    2016-09-09
  • Java 實(shí)現(xiàn)簡單Socket 通信的示例

    Java 實(shí)現(xiàn)簡單Socket 通信的示例

    這篇文章主要介紹了Java 實(shí)現(xiàn)簡單Socket 通信的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • JavaWeb后臺(tái)購物車類實(shí)現(xiàn)代碼詳解

    JavaWeb后臺(tái)購物車類實(shí)現(xiàn)代碼詳解

    這篇文章主要介紹了JavaWeb后臺(tái)購物車類實(shí)現(xiàn)代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07

最新評論

屯门区| 广德县| 二连浩特市| 阆中市| 洱源县| 汕头市| 定西市| 密山市| 民乐县| 周宁县| 曲沃县| 伊春市| 个旧市| 堆龙德庆县| 柳林县| 巩留县| 揭东县| 扎囊县| 察隅县| 海丰县| 阿拉尔市| 千阳县| 凭祥市| 舞阳县| 三台县| 射阳县| 合阳县| 崇明县| 行唐县| 辰溪县| 蒲城县| 开化县| 镇原县| 太湖县| 明星| 衢州市| 工布江达县| 丘北县| 河间市| 襄城县| 年辖:市辖区|