java自定義注解類

一、前言

  今天閱讀帆哥代碼的時候,看到了之前沒有見過的新東西, 比如java自定義注解類,如何獲取注解,如何反射內部類,this$0是什么意思? 于是乎,學習并整理了一下。

二、代碼示例

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

//自定義注解類 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @
interface MyAnnotation {String name() default "hjzgg"; }public class Main {public Main(Class cls) {Field[] fields = cls.getDeclaredFields();TestAnnotation obj = null;try {obj = (TestAnnotation)cls.getConstructors()[0].newInstance(this);//獲取內部類對象} catch (Exception e) {e.printStackTrace();}for(Field field : fields) {System.out.println(field.getName() + " " + field.getType().getName());if(!field.getName().equals("this$0")) { MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);//獲取注解類String name = annotation.name();field.setAccessible(true);try {switch(name) {case "hjzgg":switch(field.getType().getName()) {case "int":case "java.lang.Integer":field.set(obj, 555);break;case "java.lang.String":field.set(obj, "hehe");break;}break;case "lxkdd":switch(field.getType().getName()) {case "int":case "java.lang.Integer":field.set(obj, 555);break;case "java.lang.String":field.set(obj, "hehe");break;}break;default:break;}} catch (Exception e) {e.printStackTrace();}}}System.out.println(obj);}public static void main(String[] args) throws InstantiationException, IllegalAccessException {new Main(TestAnnotation.class);}class TestAnnotation{public TestAnnotation(){}@MyAnnotation(name="lxkdd")private int x;@MyAnnotationprivate String y;public int getX() {return x;}public void setX(int x) {this.x = x;}public String getY() {return y;}public void setY(String y) {this.y = y;}@Overridepublic String toString() {return "x: " + x + ", y: " + y; }} }

三、代碼分析

  1.如何編寫自定義注解

public @interface MyAnnotation {   String value() default "hahaha";   
}  

  感覺等價于

public class MyAnnotation extends java.lang.annotation.Annotation{   private String value = "hahaha";   public void setValue(String value){   this.value = value;   }   public String getValue(){   return value;   }   
} 

  自定義注解類規則

  @interface實際上是繼承了java.lang.annotation.Annotation,所以定義annotation時不能繼承其他annotation或interface.?java.lang.annotation.Retention告訴編譯器如何對待 Annotation,使用Retention時,需要提供java.lang.annotation.RetentionPolicy的枚舉值.

public enum RetentionPolicy {   SOURCE, // 編譯器處理完Annotation后不存儲在class中   CLASS, // 編譯器把Annotation存儲在class中,這是默認值   RUNTIME // 編譯器把Annotation存儲在class中,可以由虛擬機讀取,反射需要   
}   

  ? java.lang.annotation.Target告訴編譯器Annotation使用在哪些地方,使用需要指定java.lang.annotation.ElementType的枚舉值.

public enum ElementType {   TYPE, // 指定適用點為 class, interface, enum   FIELD, // 指定適用點為 field   METHOD, // 指定適用點為 method   PARAMETER, // 指定適用點為 method 的 parameter   CONSTRUCTOR, // 指定適用點為 constructor   LOCAL_VARIABLE, // 指定使用點為 局部變量   ANNOTATION_TYPE, //指定適用點為 annotation 類型   PACKAGE // 指定適用點為 package   
}   

?  ?java.lang.annotation.Documented用于指定該Annotation是否可以寫入javadoc中.?
?  ?java.lang.annotation.Inherited用于指定該Annotation用于父類時是否能夠被子類繼承.?

  示例

import java.lang.annotation.ElementType;   
import java.lang.annotation.Retention;   
import java.lang.annotation.RetentionPolicy;   
import java.lang.annotation.Target;   @Documented  //這個Annotation可以被寫入javadoc   
@Inherited       //這個Annotation 可以被繼承   
@Target({ElementType.CONSTRUCTOR,ElementType.METHOD}) //表示這個Annotation只能用于注釋 構造子和方法   
@Retention(RetentionPolicy.CLASS) //表示這個Annotation存入class但vm不讀取   
public @interface MyAnnotation {   String value() default "hahaha";   
}  

  2.如何獲取自定義注解

 ??java.lang.reflect.AnnotatedElement接口提供了四個方法來訪問Annotation

public Annotation getAnnotation(Class annotationType);   
public Annotation[] getAnnotations();   
public Annotation[] getDeclaredAnnotations();   
public boolean isAnnotationPresent(Class annotationType);  

  ?來自:http://blog.csdn.net/foamflower/article/details/5946451

? ?Class、Constructor、Field、Method、Package等都實現了該接口,可以通過這些方法訪問Annotation信息,前提是要訪問的Annotation指定Retention為RUNTIME.?
? ? ?Java內置的annotation有Override Deprecated SuppressWarnings.?
? ? ?Override只用于方法,它指明注釋的方法重寫父類的方法,如果不是,則編譯器報錯.?
? ? ?Deprecated指明該方法不建議使用.
? ? ?SuppressWarnings告訴編譯器:我知道我的代碼沒問題.

  3.this$0是什么意思?

public class Outer {//this$0 public class FirstInner {//this$1 public class SecondInner {//this$2 public class ThirdInner { } } } 
}

  說一個場景:當我們拿到了一個內部類的對象Inner,但是又想獲取其對應的外部類Outer,那么就可以通過this$0來獲取。this$0就是內部類所自動保留的一個指向所在外部類的引用。?

    //通過工具獲取到Inner實例對象 Outer.Inner inner = getInner(); //獲取內部類Inner的一個字段this$0信息 //this$0特指該內部類所在的外部類的引用,不需要手動定義,編譯時自動加上 Filed outerField = inner.getClass().getDeclaredField("this$0"); //this$0是私有的,提升訪問權限 outerField.setAccessible(true); //拿到該字段上的實例值 Outer outer = (Outer)outerField.get(inner); 

  4.java如何反射內部類

Class<?> cls = Class.forName("package.OuterClass$InnerClass"); or Class<?> cls = OuterClass.InnerClass.class;
(1)OuterClass.InnerClass obj = (OuterClass.InnerClass)cls.getConstructors()[0].newInstance(new OuterClass()); 
(2)OuterClass.InnerClass obj = (OuterClass.InnerClass)cls.getConstructor(OuterClass.class).newInstance(new OuterClass());

  由此可見,內部類的無參構造器在通過反射機制獲取時,要指定其父類參數才可以獲得,否則將報如下異常:

java.lang.NoSuchMethodException: com.hjzgg.OuterClass$InnerClass.<init>()at java.lang.Class.getConstructor0(Class.java:3082)at java.lang.Class.getConstructor(Class.java:1825)

?

轉載于:https://www.cnblogs.com/hujunzheng/p/5719611.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531292.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531292.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531292.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解決cookie跨域訪問

一、前言 隨著項目模塊越來越多&#xff0c;很多模塊現在都是獨立部署。模塊之間的交流有時可能會通過cookie來完成。比如說門戶和應用&#xff0c;分別部署在不同的機器或者web容器中&#xff0c;假如用戶登陸之后會在瀏覽器客戶端寫入cookie&#xff08;記錄著用戶上下文信息…

React使用antd Table生成層級多選組件

一、需求 用戶對不同的應用需要有不同的權限&#xff0c;用戶一般和角色關聯在一起&#xff0c;新建角色的時候會選擇該角色對應的應用&#xff0c;然后對應用分配權限。于是寫了一種實現的方式。首先應用是一個二級樹&#xff0c;一級表示的是應用分組&#xff0c;二級表示的是…

junit4進行單元測試

一、前言 提供服務的時候&#xff0c;為了保證服務的正確性&#xff0c;有時候需要編寫測試類驗證其正確性和可用性。以前的做法都是自己簡單寫一個控制層&#xff0c;然后在控制層里調用服務并測試&#xff0c;這樣做雖然能夠達到測試的目的&#xff0c;但是太不專業了。還是老…

快速搭建springmvc+spring data jpa工程

一、前言 這里簡單講述一下如何快速使用springmvc和spring data jpa搭建后臺開發工程&#xff0c;并提供了一個簡單的demo作為參考。 二、創建maven工程 http://www.cnblogs.com/hujunzheng/p/5450255.html 三、配置文件說明 1.application.properties jdbc.drivercom.mysql.jd…

dubbo服務提供與消費

一、前言 項目中用到了Dubbo&#xff0c;臨時抱大腿&#xff0c;學習了dubbo的簡單實用方法。現在就來總結一下dubbo如何提供服務&#xff0c;如何消費服務&#xff0c;并做了一個簡單的demo作為參考。 二、Dubbo是什么 Dubbo是一個分布式服務框架&#xff0c;致力于提供高性能…

git親測命令

一、Git新建本地分支與遠程分支關聯問題 git checkout -b branch_name origin/branch_name 或者 git branch --set-upstream branch_name origin/branch_name 或者 git branch branch_name git branch --set-upstream-toorigin/branch_name branch_name 二、查看本地分支所關…

mysql 7下載安裝及問題解決

mysql 7安裝及問題解決 一、mysql下載 下載地址&#xff1a;https://www.mysql.com/downloads/Community (GPL) DownloadsMySQL Community Server (GPL)Windows (x86, 64-bit), ZIP ArchiveNo thanks, just start my download.二、mysql安裝 解壓到指定目錄在mysql bin目錄下打…

RestTemplate發送請求并攜帶header信息

1、使用restTemplate的postForObject方法 注&#xff1a;目前沒有發現發送攜帶header信息的getForObject方法。 HttpHeaders headers new HttpHeaders(); Enumeration<String> headerNames request.getHeaderNames(); while (headerNames.hasMoreElements()) {String k…

工作中常用到的命令

linux zip 和 unzip http://blog.csdn.net/shenyunsese/article/details/17556089 linux 查看日志 http://blog.chinaunix.net/uid-15463753-id-2943532.html linux 刪除 http://www.jb51.net/LINUXjishu/179430.html linux查看末尾日志&#xff08;tail -f&#xff09; http:/…

tomcat開發遠程調試端口以及利用eclipse進行遠程調試

一、tomcat開發遠程調試端口 方法1 WIN系統 在catalina.bat里&#xff1a;   SET CATALINA_OPTS-server -Xdebug -Xnoagent -Djava.compilerNONE -Xrunjdwp:transportdt_socket,servery,suspendn,address8899   Linux系統 在catalina.sh里&#xff1a;   CATALINA_OPTS&q…

webpack+react+redux+es6開發模式

一、預備知識 node, npm, react, redux, es6, webpack 二、學習資源 ECMAScript 6入門 React和Redux的連接react-redux Redux 入門教程 redux middleware 詳解 Redux研究 React 入門實例教程 webpack學習demo NPM 使用介紹 三、工程搭建 之前有寫過 webpackreactes6開發模式…

fiddler發送post請求

1.指定為 post 請求&#xff0c;輸入 url Content-Type: application/x-www-form-urlencoded;charsetutf-8 request body中的參數格式&#xff1a;userNameadminicxp&userPassword123qwe!# 這種方式可以用 request.getParameter的方式來獲得。 2.指定為 post 請求&#xff…

基于spring注解AOP的異常處理

一、前言 項目剛剛開發的時候&#xff0c;并沒有做好充足的準備。開發到一定程度的時候才會想到還有一些問題沒有解決。就比如今天我要說的一個問題&#xff1a;異常的處理。寫程序的時候一般都會通過try...catch...finally對異常進行處理&#xff0c;但是我們真的能在寫程序的…

Kettle之數據抽取、轉換、裝載

Kettle 官網 ETL利器Kettle實戰應用解析系列 利用kettle組件導入excel文件到數據庫 kettle中實現動態SQL查詢 java中調用kettle轉換文件 kettle 7.x版本下載&#xff1a;https://pan.baidu.com/s/1nvnzzCH  密碼&#xff1a;6f5c mac 下運行spoon.sh,  windows下為spoon.bat…

webpack+react+redux+es6開發模式---續

一、前言 之前介紹了webpackreactreduxes6開發模式 &#xff0c;這個項目對于一個獨立的功能節點來說是沒有問題的。假如伴隨著源源不斷的需求&#xff0c;前段項目會涌現出更多的功能節點&#xff0c;需要獨立部署運行。為了更好地管理這些獨立的功能節點&#xff0c;我們需要…

JdbcTemplate使用小結

org.springframework.jdbc.core.JdbcTemplate.query(String sql, Object[] args, RowMapper<StaffUnionVO> rowMapper) throws DataAccessException 1.自定義rowMapper public class StaffUnionVO implements RowMapper<StaffUnionVO>, Serializable {private stat…

RabbitMQ安裝和使用(和Spring集成)

一、安裝Rabbit MQ   Rabbit MQ 是建立在強大的Erlang OTP平臺上&#xff0c;因此安裝Rabbit MQ的前提是安裝Erlang。通過下面兩個連接下載安裝3.2.3 版本&#xff1a; 下載并安裝 Eralng OTP For Windows (vR16B03)運行安裝 Rabbit MQ Server Windows Installer (v3.2.3)具體…

單點登錄實現(spring session+redis完成session共享)

一、前言 項目中用到的SSO&#xff0c;使用開源框架cas做的。簡單的了解了一下cas&#xff0c;并學習了一下 單點登錄的原理&#xff0c;有興趣的同學也可以學習一下&#xff0c;寫個demo玩一玩。 二、工程結構 我模擬了 sso的客戶端和sso的服務端&#xff0c; sso-core中主要是…

maven deploy上傳私服出錯

error 內容如下 Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.5: deploy (default-deploy) on project XXX pom文件增加如下配置 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifa…

加密策略

一、前言 這兩天研究了一下項目中的密碼加密&#xff0c;可以說得上是學到了很多。下面來大致說一下。 二、常用加密 1.單向加密算法 單向加密算法主要用來驗證數據傳輸的過程中&#xff0c;是否被篡改過。 BASE64 嚴格地說&#xff0c;屬于編碼格式&#xff0c;而非加密算法 …