注解Annotation

2019-07-28  本文已影响0人  一条小团团OvO

一.注解的写法
@name[(信息,可有可不有)]
二.注解写在哪里
放在类上面 属性上面 方法上面 构造方法上面 参数前面
三.注解的作用
1.充当注释的作用(仅仅是文字的说明)
2.用来做代码的检测验证
3.可以携带一些内容(信息)
四.java中写好的注解
@Deprecated 方法已废弃(注释)
@override 方法重写(检测)
@SuppressWarnings({String类型的数组})
unused 变量未使用
serial 序列化的版本号
rawTypes 没用写泛型
五.注解可以携带信息,也可以不携带,但只能是如下类型;
1.基本数据类型
2.String 字符串
3.枚举类型

  1. 数组[]类型
    5.注解类型
    六.如何自己描述一个注解类型
    1.通过@interface定义一个新的注解类型
    2.发现与接口非常相似(可以利用接口的方式来记忆注解)
    可以描述抽象方法,方法的返回值必须要有,只能是上面哪些
    可以描述属性(比较少见,不推荐使用)
public @interface Annotation {

}

3.我们自己定义的注解想要拿来用,必须做很多细致的说明(需要利用java提供的元注解来说明)
元注解(也是注解,不是拿来用的,而是拿来说明注解的)
3.1@Target({ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,...})描述当前的这个注解可以放置在哪里写
3.2@Retention(RetentionPolicy.RUNTIME)描述当前的注解存在什么作用域中
源代码文件--->编译--->字节码文件--->加载---->内存执行
SOURCE------------------CLASS---------------------RUNTIME
3.3@Inherited描述当前注解是否能被子类对象继承
3.4@Document描述这个注解能否被文档记录
4.自己使用注解

package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD})
//写一个方法方法名尽量写value,这样得到注解的时候可以不写方法名
public @interface Annotation {
    String value();
    String test();
}

package annotation;

public class test {
    @Annotation(value ="ABC",test="aaa")
    private String name;
}

如何解析注解内携带的内容(反射机制)
注解应用场景
六.反射解析注解+注解应用
1.获取属性上的注解的信息

package annotation;

public class Person {
    @MyAnnotation(value = {"abc","aaa"})
    private String name;

}
package annotation;

//import java.lang.annotation.MyAnnotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class test {
    public static void main(String[] args) {
       test test=new test();
       test.getFieldAnnotation();
    }
    /**
     * 利用反射机制获取属性上的注解的信息
     */
    public void getFieldAnnotation(){
        //首先获取那个写了注解的类
        Class clazz=Person.class;
        //找到你写了注解的那个属性
        try {
            Field name=clazz.getDeclaredField("name");
            //通过属性获取注解对象
//=============================================比较low的方法,通过对象直接调用方法,且不通用
//            MyAnnotation a=name.getAnnotation(MyAnnotation.class);
//           String[] values= a.value();
//            for (String value:values) {
//                System.out.println(value);
//            }
//===============通过反射来执行方法
            Annotation a=name.getAnnotation(MyAnnotation.class);
            //获取自定义的注解类
            Class aclazz=a.getClass();
            //获取value方法
            Method amethod=aclazz.getMethod("value");
            String[] values=(String[]) amethod.invoke(a);
                        for (String value:values) {
               System.out.println(value);
           }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

效果图:


效果.PNG

2.获取方法上的注解的信息,同上.
3.设计一个方法传入一个字符串,返回一个对象,且对象已经赋值

package annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class MySpring {
    /*
    * 设计一个方法,给一个类名,返回一个对象,对象内的属性值存在着
    *
    * */
    public static Object getBean(String className){
        Object object=null;
        try {
            Class clazz=Class.forName(className);//要求参数是类全名
            //1.通过clazz创建一个对象
            //找到无参的构造方法
            Constructor con=clazz.getConstructor();
            object=con.newInstance();
            //3.将对象内的所有属性自动赋值,DI
            Annotation a=con.getAnnotation(MyAnnotation.class);
            Class aclazz=a.getClass();
            //获取value方法
            Method amethod=aclazz.getMethod("value");
            String[] values=(String[]) amethod.invoke(a);
           // Field[] fields=clazz.getFields();
            Field[] fields=clazz.getDeclaredFields();
         //   for (String value:values) {
                /*
                *赋值,找到那个对应的属性,
                * 可以直接通过Field[] fields=clazz.getFields();
                * 但这种方式没有通用性,所以可以通过set方法赋值
                 */
                int i=0;
                for (Field field:fields) {
                    //获取属性名
                    String fieldName=field.getName();
                    //手动拼接字符串,拼接属性对应的set方法名,StringBuilder性能比String拼接好;
                    StringBuilder setMethodName=new StringBuilder("set");
                    setMethodName.append(fieldName.substring(0,1).toUpperCase());//属性首字母大写拼接
                    setMethodName.append(fieldName.substring(1));//其余部分拼接
                    //获取field对应的属性类型
                    Class fieldType=field.getType();
                  //  System.out.println(fieldType.getName());
                    //获取set方法
                    Method method=clazz.getMethod(setMethodName.toString(),fieldType);
                    /**
                     * method.invoke(object,value);
                     *小bug只能处理String类型的数据
                     * */
                    Constructor conv=fieldType.getConstructor(String.class);//通过包装类的String构造方法
                    method.invoke(object,conv.newInstance(values[i]));//将String转成属性的类型
                i++;
                }
           // }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
}

总结:


Annotationee.PNG
上一篇下一篇

猜你喜欢

热点阅读