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;
        @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)
时间: 2024-08-08 01:21:56

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

深入 Java自定义注解

我们在使用Spring框架的时候,会经常使用类似:@Autowired 这样的注解.我们也可以自己定义一些注解.Java的注解主要在包:java.lang.annotation中实现. 1. 元注解 什么是元注解?你可以这样理解,元注解是自定义注解的注解.元注解主要包含4个.他们主要在java.lang.annotation中可以找到.我们自己要创建注解的时候必须要用到这些元注解.所以必须彻底理解这四个元注解的含义. 1. @Documented 2. @Inherited 3. @Retent

Java自定义注解反射校验数据

package com.annotations.ecargo; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUN

java自定义注解并解读

不多说,先看例子,通过例子来说这个自定义注解. 自己定义了一个注解类testType: package com.zhudan.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(Retention

Java自定义注解

自定义注解类编写的一些规则: 1. Annotation型定义为@interface, 所有的Annotation会自动继承Java.lang.Annotation这一接口,并且不能再去继承别的类或是接口. 2. 参数成员只能用public或默认(default)这两个访问权修饰 3. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String.Enum.Class.annotations等数据类型,以及这一些类

转!java自定义注解

转自:http://blog.csdn.net/yixiaogang109/article/details/7328466  Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能.注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annotation 包中. 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1.1.@Retention

Java自定义注解的使用

最近学习了一下Java的自定义注解,终于知道了框架那些注解是咋个写出来的了,以后我也可以自己写框架,自己定义注解,听着是不是很牛的样子?不要心动,赶快行动,代码很简单,一起来学习一下吧! 这个例子是模仿框架的一个对sql拼装的例子,用注解实现对model也就是实体类的注释,就可以写出查询该字段的sql.好了,废话少说,一看代码便知.大家可以根据自己的需求修改. package com.annotation.demo; import java.lang.annotation.Documented;

java 自定义注解以及获得注解的值

1.自定义注解 import java.lang.annotation.*; @Documented @Target(ElementType.FIELD) @Inherited @Retention(RetentionPolicy.RUNTIME ) public @interface MyAnno { /** * 是否能为null * @return */ boolean isCanNull() default true; /** * 是否能为空字符串 * @return */ boolean

Java 自定义注解及利用反射读取注解

一.自定义注解 元注解: @interface注解: 定义注解接口 @Target注解: 用于约束被描述的注解的使用范围,当被描述的注解超出使用范围则编译失败.如:ElementType.METHOD,ElementType.TYPE: @Retention 注解:用于约束被定义注解的作用范围,作用范围有三个: 1,.RetentionPolicy.SOURCE:作用范围是源码,作用于Java文件中,当执行javac时去除该注解. 2.RetentionPolicy.CLASS:作用范围是二进制

【面试加分项】java自定义注解之申明注解

之前的博客http://blog.csdn.net/u010590685/article/details/47029447介绍了java的注解的基本知识今天我们学习如何使用自定义注解. 首先我们要声明一个注解,声明代码如下: import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.