一、前言

  今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如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;
@MyAnnotation
private 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;
} @Override
public 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)

java自定义注解类的更多相关文章

  1. java自定义注解注解方法、类、属性等等【转】

    http://anole1982.iteye.com/blog/1450421 http://www.open-open.com/doc/view/51fe76de67214563b20b385320 ...

  2. java自定义注解实现前后台参数校验

    2016.07.26 qq:992591601,欢迎交流 首先介绍些基本概念: Annotations(also known as metadata)provide a formalized way ...

  3. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

  4. Android面试基础(一)IOC(DI)框架(ViewUtils)讲解_反射和自定义注解类

    1. Android中的IOC(DI)框架 1.1 ViewUtils简介(xUtils中的四大部分之一) IOC: Inverse of Controller 控制反转. DI: Dependenc ...

  5. Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)

    Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性) 前言:由于前段时间忙于写接口,在接口中需要做很多的参数校验,本着简洁.高效的原则,便写了这个小工具供自己使用(内容 ...

  6. JAVA自定义注解 ------ Annotation

    日常开发工作中,合理的使用注解,可以简化代码编写以及使代码结构更加简单,下面记录下,JAVA自定义注解的开发过程. 定义注解声明类. 编写注解处理器(主要起作用部分). 使用注解. 相关知识点介绍, ...

  7. Java自定义注解和运行时靠反射获取注解

    转载:http://blog.csdn.net/bao19901210/article/details/17201173/ java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编 ...

  8. Java自定义注解的实现

    Java自定义注解的实现,总共三步(eg.@RandomlyThrowsException): 1.首先编写一个自定义注解@RandomlyThrowsException package com.gi ...

  9. Java中自定义注解类,并加以运用

    在Java框架中,经常会使用注解,而且还可以省很多事,来了解下自定义注解. 注解是一种能被添加到java代码中的元数据,类.方法.变量.参数和包都可以用注解来修饰.注解对于它所修饰的代码并没有直接的影 ...

随机推荐

  1. JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome

    今天为大家分享一下我自己制作的浏览器滚动条,我们知道用css来自定义滚动条也是挺好的方式,css虽然能够改变chrome浏览器的滚动条样式可以自定义,css也能够改变IE浏览器滚动条的颜色.但是css ...

  2. IE10、IE11 User-Agent 导致的 ASP.Net 网站无法写入Cookie 问题

    你是否遇到过当使用一个涉及到Cookie操作的网站或者管理系统时,IE 6.7.8.9下都跑的好好的,唯独到了IE10.11这些高版本浏览器就不行了?好吧,这个问题码农连续2天内遇到了2次.那么,我们 ...

  3. 【Net跨平台第一步】逆天带你零基础Linux入门【更新完毕】

    部分讲义:(视频已删,后期以文档形式发布)

  4. jquery.Callbacks的实现

    前言 本人是一个热爱前端的菜鸟,一直喜欢学习js原生,对于jq这种js库,比较喜欢理解他的实现,虽然自己能力有限,水平很低,但是勉勉强强也算是能够懂一点吧,对于jq源码解读系列,博客园里有很多,推荐大 ...

  5. 如何在网页中提取Email地址

    开博好久了,今天第一次发表技术文档,之前总是将一些好的事例保存在电脑,时间久了找起来也很麻烦,所以还是放在博客里进行归类比较方便,这样也能将自己在学习过程中的一些心得体会分享给大家,也能给需要的人一点 ...

  6. SELECT INTO 和 INSERT INTO SELECT 两种表复制语句

    Insert是T-sql中常用语句,Insert INTO table(field1,field2,...) values(value1,value2,...)这种形式的在应用程序开发中必不可少.但我 ...

  7. P2V之后的磁盘扩容新思路

    背景: 原先的物理机环境多是若干块物理磁盘经过RAID卡进行了RAID5之后的虚拟磁盘组,这样我们在操作系统内看到的也就是一块完整的磁盘.我们会在上面进行分区,然后格式化后以便使用. Figure 1 ...

  8. js数组去重几种思路

    在一些后台语言中都内置了一些方法来处理数组或集合中重复的数据.但是js中并没有类似的方法,网上已经有一些方法,但是不够详细.部分代码来源于网络.个人总计如下:大致有4种思路 1)使用两次循环比较原始的 ...

  9. 中文 iOS/Mac 开发博客列表

    中文 iOS/Mac 开发博客列表 博客地址 RSS地址 OneV's Den http://onevcat.com/atom.xml 一只魔法师的工坊 http://blog.ibireme.com ...

  10. AEAI DP V3.7.0 发布,开源综合应用开发平台

    1  升级说明 AEAI DP 3.7版本是AEAI DP一个里程碑版本,基于JDK1.7开发,在本版本中新增支持Rest服务开发机制(默认支持WebService服务开发机制),且支持WS服务.RS ...