【JAVA注解与反射】

一. 注解
Java 定义了一套注解,共有10 个,6个在 java.lang 中,剩下 4 个在 java.lang.annotation(元注解) 中。

(1)作用在代码的注解是

@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
@SuppressWarnings - 指示编译器去忽略注解中声明的警告。
@SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

(2)作用在其他注解的注解(或者说 元注解)是:
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解可以修饰哪些 Java 成员。
@Inherited - 如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解
常用注解
@Documented 标记这些注解是否包含在用户文档中。
@Inherited 可以继承

/**
 * @Retention()
 *
 * RetentionPolicy.SOURCE //源码级别保留,编译后即丢弃。
 *
 * RetentionPolicy.CLASS //编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。
 *
 * RetentionPolicy.RUNTIME // 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。
 *
 * @Target()
 *
 * ElementType.TYPE //类,接口或者枚举
 *
 * ElementType.FIELD //域,包含枚举常量
 *
 * ElementType.METHOD //方法
 *
 * ElementType.PARAMETER //参数
 *
 * ElementType.CONSTRUCTOR //构造方法
 *
 * ElementType.LOCAL_VARIABLE //局部变量
 *
 * ElementType.ANNOTATION_TYPE //注解类型
 *
 * ElementType.PACKAGE //包
 *
 * ElementType.TYPE_PARAMETER //类型参数声明(1.8)
 *
 * ElementType.TYPE_USE //使用类型(1.8)
 */
@Target( {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String name();
}

二.反射
修饰符在反射面前一文不值
注意我在这里用private修饰过的,在使用反射时可以拿到
这里先搞一个user类

package reflection;

import annotation.MyAnnotation;
import annotation.Singleton;

@Singleton
@MyAnnotation
public class User {
    @MyAnnotation
    public Integer ID;
    private String name;
    private Integer age;
    @MyAnnotation
    public User(Integer ID, String name, Integer age) {
        this.ID = ID;
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    public Integer getID() {
        return ID;
    }

    public void setID(Integer ID) {
        this.ID = ID;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
    @MyAnnotation
    public void eating(){
        System.out.println("我正在吃");
    }
    private void eating(String FoodsName){
        System.out.println("我正在吃"+FoodsName);
    }

    @Override
    public String toString() {
        return "User{" +
                "ID=" + ID +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


然后在进行获取class对象进行使用
private修饰过的,依旧可以被搞定

package reflection;

import annotation.MyAnnotation;
import org.junit.Before;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;

public class Test {
    /**
     * 0.创建拿到反射类
     * 1.反射拿到成员变量
     * 2.反射拿到成员方法
     * 3.反射拿到构造器
     * 4.反射拿到注解
     */

    Class<User> clazz = null;

    @Before
    public void create() {
        clazz = User.class;
    }

    @org.junit.Test
    public void CreateReflection() throws ClassNotFoundException {
        //使用类
        Class<User> class1 = User.class;
        //使用对象
        User user = new User();
        Class<? extends User> class2 = user.getClass();

        //使用全类名
        Class<?> class3 = Class.forName("reflection.User");

    }

    //对类对象的操作
    @org.junit.Test
    public void objectTest() throws InstantiationException, IllegalAccessException {
        //获取类名字
        String name = clazz.getName();
//获取类加载器
        ClassLoader classLoader = clazz.getClassLoader();
//获取资源
        URL resource = clazz.getResource("");
//得到父类
        Class superclass = clazz.getSuperclass();
//判断一个类是不是接口,数组等等
        boolean array = clazz.isArray();
        boolean anInterface = clazz.isInterface();

//重点,使用class对象实例化一个对象
        Object instance = clazz.newInstance();
    }

    //获取对象的操作
    public void GetVariable() throws NoSuchFieldException {
        //获取字段,只能获取公共的字段(public)
        Field name = clazz.getField("name");
        Field[] fields = clazz.getFields();
//能获取所有的字段包括private
        Field ID = clazz.getDeclaredField("ID");
        Field[] fields2 = clazz.getDeclaredFields();


    }

    //对类成员变量的操作
    @org.junit.Test
    public void variableTest() throws NoSuchFieldException, IllegalAccessException {
        /**
         * 成员变量与类方法,构造器大同小异
         */
        User user = new User();
        user.setAge(12);
        user.setID(1);
        user.setName("zhangsan");
        Field id = clazz.getField("ID");
        id.set(user, 2);
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(user, "lisi");
        Field age = clazz.getDeclaredField("age");
        age.setAccessible(true);
        age.set(user, 17);
        System.out.println(user);

    }

    //对类成员方法的操作
    @org.junit.Test
    public void MethodTest() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        user.setID(12);
//获取某个方法,名字,后边是参数类型
        Method method = clazz.getDeclaredMethod("eating", String.class);
        method.setAccessible(true);
//拿到参数的个数
        int parameterCount = method.getParameterCount();
//拿到方法的名字
        String name = method.getName();
//拿到参数的类型数组
        Class<?>[] parameterTypes = method.getParameterTypes();
//拿到返回值类型
        Class<?> returnType = method.getReturnType();
//重点。反射调用方法,传一个实例,和参数
        method.invoke(user, "热狗");
        System.out.println(name);

    }

    //对类构造器的操作
    @org.junit.Test
    public void ConstructorTest() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Constructor[] constructors = clazz.getConstructors();
        Constructor constructor = clazz.getConstructor(Integer.class, String.class, Integer.class);
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        Constructor declaredConstructor = clazz.getDeclaredConstructor();
        User user = (User) constructor.newInstance(1, "lisi", 12);
        System.out.println("User = " + user.getName());
    }

    //对注解的操作
    @org.junit.Test
    public void AnnoationTest() throws NoSuchFieldException, NoSuchMethodException {
        //获取注解的名字
        MyAnnotation declaredAnnotation = clazz.getAnnotation(MyAnnotation.class);
        System.out.println("declaredAnnotation.name() = " + declaredAnnotation.name());


        //拿到所有注解
        Annotation annotation = clazz.getAnnotation(MyAnnotation.class);
        Annotation[] annotations = clazz.getAnnotations();

//字段上
        Field field = clazz.getDeclaredField("name");
        Annotation annotation1 = field.getAnnotation(MyAnnotation.class);
        Annotation[] annotations1 = field.getAnnotations();

//方法上
        Method method = clazz.getDeclaredMethod("eating", String.class);
        Annotation annotation2 = method.getAnnotation(MyAnnotation.class);
        Annotation[] annotations2 = method.getAnnotations();
    }
}

小案例
在以后学到框架的时候可以通过不同的注解来做具体的操作,
当前的具体实现小案例在SingletonHandler中只是具体的简单创造了一下实例,在以后的框架中会有更深层次的学习,装载在维护上下文的环境中

主函数

package reflection;

import context.ApplicationContext;
import handler.SingletonHandler;
import reflection.Utils.FileUtils;

import java.io.File;
import java.net.URL;
import java.util.List;

public class BootStrap {
    //在类加载之后处理 启动慢 运行快
    static {
        //获得当前根路径的绝对路径(用来替换的工具)
        final URL resource = Thread.currentThread().getContextClassLoader().getResource("");
        List<String> classNames = FileUtils.getClassName(new File(resource.getFile()));
        SingletonHandler.handler(classNames);
        /**在这之前装填了所有属于当前根路径的class(添加了sington注解的)
         * 维护在上下文中
        */
    }
    public static void main(String[] args) {
        //这里直接可以通过方法拿到添加了sington注解的实例User的实例
        User user = ApplicationContext.getSington(User.class);
        System.out.println(user);
    }

}


维护的上下文

package context;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ApplicationContext {
    //维护一个上下文环境
    public static final Map<Class<?>,Object> context=new ConcurrentHashMap<>();
//维护一个上下文
    public static void addSington(Class<?> clazz,Object entity) {
        ApplicationContext.context.put(clazz,entity);
    }
//拿到上下文的实例
    public static <T>T getSington(Class<?> clazz) {
       return (T)ApplicationContext.context.get(clazz);
    }
}
















获取路径的工具包

package reflection.Utils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class FileUtils {
    //找绝对路径的文件名
    private static void  findclass(String path, List<String> classPathList) {
        //拿到文件
        File file = new File(path);
        //文件化集合 并且过滤
        File[] clazz = file.listFiles(((dir, name) -> new File(dir, name).isDirectory() || name.contains("class")));
        //判断是否为空
        if (clazz == null || clazz.length == 0) {
            return;
        }
        //在不为空的情况下进行遍历
        for (File list : clazz) {
            if (list.isDirectory()) {
                findclass(list.getAbsolutePath(), classPathList);
            } else {
                classPathList.add(list.getAbsolutePath());
            }
        }
    }

    public static List<String> getClassName(File file) {
        List<String> classpaths = new ArrayList<>();
        findclass(file.getAbsolutePath(), classpaths);
        //[D:\ydl\practice\out\production\annotation\reflection\BootStrap.class,把这个绝对路径转换为全限定名称]
        //用流做映射,转换函数给他返回出去为annotation.reflection.BootStrap
        List<String> collect = classpaths.stream().map(path -> {
            String fileName = file.getAbsolutePath();
            return path.replace(fileName + "\\", "").replaceAll("\\\\", ".").replace(".class", "");
        }).collect(Collectors.toList());
        return collect;
    }
}

单例注解

package annotation;

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Singleton {
}

为了转载在上下文中的解析器

package handler;

import annotation.Singleton;
import context.ApplicationContext;

import java.util.List;

public class SingletonHandler {
    public static void handler(List<String> classNames) {
        for (String className : classNames) {
            Class<?> clazz = null;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            assert clazz != null;
            Singleton annotation = clazz.getDeclaredAnnotation(Singleton.class);
            if (annotation != null) {
                Object instance = null;
                try {
                    instance = clazz.newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                ApplicationContext.addSington(clazz,instance);
            }
        }
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长安归故里♬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值