#博学谷IT学习技术支持#

1案例的类

import com.example.demo3.fanshe.MyAnnotation;
import lombok.Data;

/**
 * @author zw
 * @Description 描述
 * @create /2022/2/13
 */
@MyAnnotation("Dog class Annotation")
@Data
public class Dog {
    @MyAnnotation("Dog field-> name Annotation")
    private String name="dog旺旺";
    public String age="dog5岁";
    protected String test="test岁";
      String tesat="test岁";
    //无参构造
    public  Dog(){
        System.err.println("我是无参构造");
    }
    public void Dog(String age) {
        this.age = age;
        System.out.println("方法Dog 入参age"+age);
    }
    public void dog1(String age){
        System.err.println("我是方法dog1:"+age);
    }
    public void dog1(String age,String name){
        System.err.println("我是方法dog1==="+age+name);
    }
    //有参构造
    public Dog(String age) {
        this.age = age;
        System.out.println("有参构造age"+age);
    }
    //有参构造
    public Dog(String name, String age) {
        this.name = name;
        this.age = age;
        System.out.println("有参构造name+age"+name+age);
    }
   @MyAnnotation(value = "Dog method Annotation")
    public void testMyAnnotation(String name, String age) {
        System.out.println("testMyAnnotation:"+name+age);
    }

}


/**
 * @author zw
 * @Description 描述
 * @create /2022/2/6
 */
//value 可以自动省略
//@Target(ElementType.METHOD)
@Target(value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented //表示把注解生成在Javadoc中
@Inherited //表示可以被继承
public @interface MyAnnotation {
    String value();
}

2反射方法

2.1 获取class对象

//1三种获取反射方法
        Dog dog = new Dog();
        Class c1 = dog.getClass();//一般不用 因为反射效率低 都能new 对象了就不用反射了
         System.out.println(c1.getName()); //  com.example.demo3.fanseh.Dog
        Class c2 =Dog.class;
        Class c3 = Class.forName("com.example.demo3.fanseh.Dog");
        System.out.println(c1==c2 == c3 );//true  因为内存中只有一份这个对象

2.2  获取方法

//2 反射获取所有方法 api
        //获取所有public 修饰 方法
        Method[] methods = c2.getMethods();
        
        //获取指定方法  dog1方法 并且是public 修饰
        Method method4 = c2.getMethod("dog1", String.class, String.class);
        //调用dog1方法 后面两个是参数
        method4.invoke(c2.newInstance(),"我是name入参","我是age入参");
        
        //获取 public 修饰 所有构造方法
        Constructor[] constructors = c2.getConstructors();
        
        //获取所有的方法(包含private修饰的方法) 主要的
        Method[] declaredMethods = c2.getDeclaredMethods();
        for (Method method : declaredMethods) {
            method.getName();//方法名
            method.invoke(c2.newInstance(),"参数1","参数2");//执行方法
        }
        
        //获取指定的方法 参数一是方法名,后面是可变参,是参数类型
        Method method1 = c2.getDeclaredMethod("dog1", String.class);
        //参数一 类的实例 参数二 是参数    invoke执行这个方法
        method1.invoke(c2.newInstance(),"参数");

   手动拼接get/set方法
                                StringBuilder sb = new StringBuilder();
                                sb.append("get");
                                sb.append(fieldName.substring(0, 1).toUpperCase(Locale.ROOT));
                                sb.append(fieldName.substring(1));

2.3获取属性api

//3 获取所有的属性(包含private修饰的方法)
        Field[] declaredFields = c2.getDeclaredFields();
        Dog dog1 = new Dog();//需要赋值的对象
        String str="反射赋值";
        for (Field field : declaredFields) {
            field.setAccessible(true);//解除私有限定 要不私有属性设置值等会报错
            //获取属性名称
            String name = field.getName();
            String type = field.getType().toString();
            if (type.endsWith("String")) {
                field.set(dog1,  str); // 给属性设值
            } else if (type.endsWith("int") || type.endsWith("Integer")&&null!=str) {
                field.set(dog1, new Integer((String) str)); // 给属性设值
            }  else if (type.endsWith("BigDecimal")&&null!=str) {
                field.set(dog1, new BigDecimal((String) str)); // 给属性设值
            } else if (type.endsWith("List")&&null!=str) {
                field.set(dog1, str); // 给属性设值
            } else {
                field.set(dog1, str);
            }
        }

2.4 配合注解使用

//获取注解
        // Dog类上是否含有这个注解
        boolean annotation = c2.isAnnotationPresent(MyAnnotation.class);
        System.err.println("Dog类是否含有注解:"+annotation);//是否含有注解:true
        Method[] declaredMethods1 = c2.getDeclaredMethods();
        for (Method method2 : declaredMethods1) {
            //Dog类中 方法是否含有注解
            boolean methodAnnotation = method2.isAnnotationPresent(MyAnnotation.class);
            if(methodAnnotation){
                MyAnnotation annotation2 = method2.getAnnotation(MyAnnotation.class);
                System.out.println("注解的值"+annotation2.value());//注解的值Dog method Annotation
            }
        }
        Field[] declaredFields1 = c2.getDeclaredFields();
        Dog dog2 = new Dog();//需要赋值的对象
        dog2.setName("反射获取值");
        for (Field field : declaredFields1) {
            boolean annotationPresent = field.isAnnotationPresent(MyAnnotation.class);
            if(annotationPresent){
                MyAnnotation annotation1 = field.getAnnotation(MyAnnotation.class);
                System.out.println(annotation1.value());//Dog field-> name Annotation
                field.setAccessible(true);//设置私有属性也能获取值
                System.out.println(field.get(c2.newInstance()));//dog旺旺
                System.out.println(field.get(dog2));//反射获取值
            }
        }

2.5获取属性值

Person person = new Person();
        person.setId(1L);
        person.setAge(12);
        person.setMoney(new BigDecimal(0));
        person.setName("小黄");
        person.setAddress("北京");
        Class c1 = person.getClass();
        Field[] declaredFields = c1.getDeclaredFields();
        List<Field> allFields = new ArrayList<>(100);
        allFields.addAll(Arrays.asList(declaredFields));
        allFields.forEach(field->{
            field.setAccessible(true);
            String name = field.getName();
            try {
                // 获取指定对象的当前字段的值
                Object fieldVal  = field.get(person);//1 小黄 12 北京 0
               String  value = name.substring(0, 1).toUpperCase() + name.substring(1);
                Method method = c1.getMethod("get" + value);
                // 获取指定对象的当前字段的值
                Object fieldVal2=  method.invoke(person);//1 小黄 12 北京 0
            } catch (Exception | NoSuchMethodException | InvocationTargetException e) {
                e.printStackTrace();
            }
        });

3 java反射内存图

引用别人内存图

java如何通过反射给实体注入注解_开发语言

4应用场景

1 一般的报表下载是最经常使用的(搭配自定义注解使用),看每个人封装能力和思维,封装的好,再也不用关心报表下载逻辑,只会关心数据的查询即可

2 框架的底层 ,这个一般是面试问到,所以要自己去学习,同时也是开阔思维,经典框架spring很有必要深入学习