注解和反射

反射

为了测试反射,编写一个 Cat 的测试类;

public class Cat {

    public static int  a;

    public static final String COUNTRY = "中国";

    private String name;
    private int age;

    public Cat() {
        System.out.println("调用无参构造器!!!");
    }

    public Cat(String name, int age) {
        System.out.println("调用有参构造器!!!");
        this.name = name;
        this.age = age;
    }

    private void eat(){
        System.out.println("爱吃猫粮~~~");
    }

    private String eat(String name){
        return "爱吃" + name;
    }


    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

反射获得构造器对象

@Test
    public void testGetConstructor() throws Exception{
        //得到这个类的Class对象
        Class c = Cat.class;

        //获取全部的构造器
        Constructor[] constructors = c.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }


        //获取某个类的构造器。无参构造器
        Constructor constructor = c.getDeclaredConstructor();

        System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());

        //禁止检查访问权限
        constructor.setAccessible(true);
        //调用构造器对象表示的构造器,并传入参数,完成对对象的初始化
        Cat cat = (Cat) constructor.newInstance();
        System.out.println(cat);

        //获得有参数的构造器
        Constructor constructor1 = c.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount());

        constructor1.setAccessible(true);
        Cat cat1 = (Cat) constructor1.newInstance("加菲猫", 3);
        System.out.println(cat1);
}

反射获得成员变量

 @Test
    public void testGetFields() throws Exception {
        //获得类的Class对象
        Class c = Cat.class;

        //获取类的全部从成员变量
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName() + "--->" + field.getType());
        }

        //定位某个成员变量
        Field fname = c.getDeclaredField("name");
        System.out.println(fname.getName() + "-->" + fname.getType());


        Field fage = c.getDeclaredField("age");
        System.out.println(fage.getName() + "-->" + fage.getType());

        //为某个成员变量赋值
        fname.setAccessible(true);
        fage.setAccessible(true);
        Cat cat = new Cat();
        fname.set(cat,"加菲猫");
        fage.set(cat,18);
        System.out.println(cat);

        System.out.println(fname.get(cat));
        System.out.println(fage.get(cat));
}

反射获得成员方法

 @Test
    public void testGetMethod() throws Exception {
        //获得类的Class对象
        Class c = Cat.class;

        //获取全部方法
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName() + "-->"
                    + method.getParameterCount() + "--->"
                    + method.getReturnType());
        }

        //获取单个方法
        Method eat = c.getDeclaredMethod("eat");
        System.out.println(eat.getName() + "-->"
                + eat.getParameterCount() + "--->"
                + eat.getReturnType());


        Method eat1 = c.getDeclaredMethod("eat",String.class);
        System.out.println(eat1.getName() + "-->"
                + eat1.getParameterCount() + "--->"
                + eat1.getReturnType());

        //触发获得的方法
        Cat cat = new Cat();
        eat.setAccessible(true);
        eat1.setAccessible(true);

        Object invoke = eat.invoke(cat);
        System.out.println(invoke);
        String invoke1 = (String) eat1.invoke(c, "草鱼");
        System.out.println(invoke1);
    }

注解

注解本质就是一个接口,java中所有注解都继承 Annotation 接口;

@注解(…):其实就是一个实现类对象,实现了该注解以及Annotation接口。

编写注解类

public @interface MyTest {

    String a();

    //默认为true
    boolean b() default true;

    String[] c();

    //特殊属性(若只有他一个属性,可以不写value直接写值)
    String value();


}

使用注解

//这里其实就是在创建一个实现类对象
@MyTest(a = "孙行者",c = {"java1","java2"},value = "2")
public class AnnotationTest01 {

    @MyTest(a = "无忌",c = {"java1","java2"},value = "3")
    public void test1(){

    }

    public static void main(String[] args) {}
}

使用工具进行反编译

import java.lang.annotation.Annotation;

public interface MyTest
	extends Annotation
{

	public abstract String a();

	public abstract boolean b();

	public abstract String[] c();

	public abstract String value();
}

元注解

修饰注解的注解;

  • @Target 作用:声明被修饰的注解只能在哪些位置使用
    @Target(ElementType.TYPE)

    TYPE,类,接口

    FIELD,成员变量

    METHOD,成员方法PARAMETER,方法参数

    CONSTRUCTOR,构造器

    LOCAL_VARIABLE,局部变量

  • @Retention作用:声明注解的保留周期。

    @Retention(RetentionPolicy.RUNTIME)

    SOURCE 只作用在源码阶段,字节码文件中不存在。

    CLASS(默认值) 保留到字节码文件阶段,运行阶段不存在。

    RUNTIME(开发常用) 一直保留到运行阶段。

注解的解析

  • 解析类上的注解
 @Test
    public void parseClass() throws Exception {
        //得到class对象
        Class c = AnnotationTest01.class;
        //解析类上的注解
        //判断类上是否包含了某个注解
        if (c.isAnnotationPresent(MyTest.class)) {
            MyTest my = (MyTest) c.getDeclaredAnnotation(MyTest.class);
            System.out.println(my.a());
            System.out.println(my.b());
            System.out.println(Arrays.toString(my.c()));
            System.out.println(my.value());
        }
    }
  • 解析方法上的注解
 @Test
    public void parseMethod() throws Exception{
        //得到class对象
        Class c = AnnotationTest01.class;
        Method m = c.getDeclaredMethod("test1");
        //解析方法上的注解
        //判断方法上是否包含了某个注解
        if (m.isAnnotationPresent(MyTest.class)){
            MyTest my = m.getDeclaredAnnotation(MyTest.class);
            System.out.println(my.a());
            System.out.println(my.b());
            System.out.println(Arrays.toString(my.c()));
            System.out.println(my.value());
        }
    }

模拟junit

加注解的方法执行,不加的不执行。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AnnotationTest02 {

    public void test1(){
        System.out.println("*******test1*******");
    }

    @JunitTest
    public void test2(){
        System.out.println("*******test2*******");
    }


    public void test3(){
        System.out.println("*******test3*******");
    }

    @JunitTest
    public void test4(){
        System.out.println("*******test4*******");
    }


    public static void main(String[] args) throws Exception {

        AnnotationTest02 a = new AnnotationTest02();

        //得到类的class对象
        Class c = AnnotationTest02.class;
        //提取这个类中全部的成员方法
        Method[] methods = c.getDeclaredMethods();

        //遍历数组中的每个方法,查看是否又@JunitTest注解
        for (Method method : methods) {
            if (method.isAnnotationPresent(JunitTest.class)){
                method.invoke(a);
            }
        }

    }

}
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值