1、自定义的MyAnnotation注解

package com.ydlclass.reflect;

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

@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)

public @interface MyAnnotation {
    String name() default "铁蛋";
}

2、Dog类


package com.ydlclass.reflect;

import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@MyAnnotation
public class Dog {

    private String name;
    public int age;

    public Dog() {
    }
    @MyAnnotation(name = "有参构造")
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Dog(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @MyAnnotation(name = "吃方法")
    public void eat(){
        eat(null);
    }

    public void eat(String foodName){
        System.out.println(this.getName() + "正在吃:" + foodName);
    }
}

3、反射的常见获取构造器创建对象,获取字段设置字段,获取不同的重载方法,获取特定的注解

package com.ydlclass.reflect;

import org.junit.Test;

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;

public class ReflectTest {
    Class<Dog> aClass = Dog.class;

    @Test
    public void classTest(){
        ClassLoader classLoader = aClass.getClassLoader();//可以从classPAth中加载对应的类,out目录下加载
        boolean annotation = aClass.isAnnotation();//判断class对象是否是一个注释
        Dog dog = null;
        try {
            dog = aClass.newInstance();//jdk9之后,此种方式过时了
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        dog.setName("123");
        System.out.println(dog.getName());
        System.out.println(annotation);

    }

    @Test
    public void testField() throws NoSuchFieldException, IllegalAccessException {
        Field[] fields = aClass.getFields();

        for (Field field : fields) {
            System.out.println(field.getName());//直接使用此方法无法获取成员变量的名字,只能拿到public的成员变量
        }

        System.out.println("-----------");
        //可以使用这个方法获得所有的字段,自然的也就可以为所有的字段赋值
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }
        //赋值操作需要给指定的对象赋值
        Dog dog = new Dog("吴签",33);
        //获取这个对象的name字段
        Field name = aClass.getDeclaredField("name");
        //修改这个字段
        //暴力注入
        name.setAccessible(true);
        name.set(dog,"jerry");
        System.out.println(name.get(dog));
        //由于name为private修饰,所以上面的设置不能为private的值
    }
    @Test
    public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //Method[] methods = aClass.getMethods();//获取public修饰的方法
        //for (Method method : methods) {
        //    System.out.println(method.getName());
        //}
        Method[] declaredMethods = aClass.getDeclaredMethods();//获取所有的方法(不包括继承父类的方法)
        //for (Method declaredMethod : declaredMethods) {
        //    System.out.println(declaredMethod.getName());
        //}

        //获取一个方法
        Method eat = aClass.getDeclaredMethod("eat");//可以只填方法名
        Method eat1 = aClass.getDeclaredMethod("eat", String.cla***这种方式获取重载的方法,
        // 由于重载方法相同;

        //对于方法而言,就是调用方法;invoke方法中需要传入两个参数,分别为需要调用的对象,已经这个方法对应的需要的参数
        Dog dog2 = new Dog("zhangsan",123);

        eat.invoke(dog2);//重载方法直接的调用形式,eat对象是无参数的方法,所以使用时不需要传入参数

        eat1.invoke(dog2,"骨头");//eat1是有参数的方法,使用invoke对象调用这个对象的方法,需要传入这个方法需要的参数;


        /***
         * 输出为:
         * zhangsan正在吃:null
         * zhangsan正在吃:骨头
         */
    }

    @Test
    public void testConstruct() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Constructor<Dog> constructor = aClass.getConstructor();
        //获取无参构造器器,并且构造对象
        Constructor<Dog> declaredConstructor = aClass.getDeclaredConstructor();
        Dog dog = declaredConstructor.newInstance();//构造了一个对象

        //获取有参构造器,实例化对象
        Constructor<Dog> declaredConstructor1 = aClass.getDeclaredConstructor(String.class, int.class);
        Dog dog1 = declaredConstructor1.newInstance("反射狗", 666);
        System.out.println(dog1.getName());
    }

    @Test
    public void testAnnotation() throws NoSuchFieldException, NoSuchMethodException {
        //1.通过类对象获取指定的注解,获取的是注解在Dog类对象上的注解
        MyAnnotation annotation = aClass.getAnnotation(MyAnnotation.class);
        System.out.println(annotation.name());

        //2.通过制定的方法获取注解在方法上的注解

        Method eat = aClass.getDeclaredMethod("eat");
        MyAnnotation annotation1 = eat.getAnnotation(MyAnnotation.class);
        System.out.println(annotation1.name());

        //3.通过构造器的方式获取注解在构造器上面的注解
        Constructor<Dog> constructor = aClass.getConstructor(String.class, int.class);
        MyAnnotation declaredAnnotation = constructor.getDeclaredAnnotation(MyAnnotation.class);
        System.out.println(declaredAnnotation.name());

    }

}