反射 reflect

 

java类的加载
  java类的加载是指将.class文件(可能在磁盘,也可能在网络)加载到内存中,并为之生成java.lang.class对象的实例
  java中类以其全限定包名作为唯一标识,jvm中则以全限定包名和类加载器作为唯一标识。
  jvm中的类加载器有三个层次:根类加载器、扩展类加载器、系统类加载器。分别加载核心类,扩展jar包中的类以及classpath等指定的类
  对象具有两种类型:编译时类型和运行时类型。

 

 

1:功能

  获取类的各个部位对应的对象  

      Class       类
      Constructor    构造器
      Method      方法
      Field       属性
      Annotation    注解

 

 2: 对象准备

  2.1 类对象
@Data
public class User {

    private Integer id;
   @NotBeNull
public String userName; private String sex; private Integer grade; //年级 private List<Course> courseList; //课程 private User() { } public User(Integer id) { findById(id); } public User(Integer id, String userName, String sex, Integer grade) { this.id = id; this.userName = userName; this.sex = sex; this.grade = grade; courseList = new ArrayList<>(); } private User findById(Integer id) { return Utils.getUserById(id); } public List<User> listAll() { return Utils.getUsers(); } }

  2.2 接口

/**
 * 测试匿名类
 * 匿名类: 匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口
 * 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以初始化块,可以通过初始化块来完成构造器需要完成的工作。
 */
public interface AnonymousInterface {
    String print(String msg);
}

  2.3 枚举

/**
 * 枚举
 */
public enum StatusEnum {}

  2.4 注解

/**
 * 注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)          //注解作用到属性上
public @interface NotBeNull {
  
String value() default "zsc";
}

  2.5 工具

public class Utils {

    public static List<User> getUsers() {
        User user1 = new User(1, "小夏1", "男", 1);
        User user2 = new User(2, "小夏2", "男", 2);
        User user3 = new User(3, "小夏3", "男", 3);
        User user4 = new User(4, "小夏4", "男", 4);
        List<User> users = Arrays.asList(user1, user2, user3, user4);
        return users;
    }


    public static User getUserById(final Integer id) {

        List<User> users = Utils.getUsers();

        for (User user : users) {
            if (user.getId().intValue() == id) {
                return user;
            }
        }
        return null;
    }

    public static List<Course> getCourses(){
        Course course1 = new Course(1,"数学","张老师");
        Course course2 = new Course(2,"英语","刘老师");
        Course course3 = new Course(3,"汉语","王老师");
        Course course4 = new Course(4,"法语","宋老师");
        List<Course> courses = Arrays.asList(course1, course2, course3, course4);
        return courses;
    }


    public static Course getCourseById( Integer id) {

        List<Course> courses = Utils.getCourses();

        for (Course course : courses) {
            if (course.getId().intValue() == id) {
                return course;
            }
        }
        return null;
    }
}

 

3:反射获取信息

package com.draymond.reflect;

import com.draymond.reflect.entity.User;
import org.junit.Test;

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

/**
 * 反射获取类的方式
 */
public class MainTest {

//-----------------------------   获得类相关的方法   -------------------------------

    /**
     * 获取Class
     *
     * @throws ClassNotFoundException
     */
    @Test
    public void test1() throws ClassNotFoundException {
        Class clazz1 = Class.forName("com.draymond.reflect.entity.User");
        System.out.println(clazz1);     //结果:class com.draymond.reflect.entity.User

        User user = new User(1, "小夏1", "男", 1);
        Class clazz2 = user.getClass();
        System.out.println(clazz2);      //结果:class com.draymond.reflect.entity.User

        Class clazz3 = User.class;
        System.out.println(clazz3);      //结果:class com.draymond.reflect.entity.User
    }

    /**
     * 获取类的全路径
     */
    @Test
    public void test2() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        String name = clazz.getName();
        System.out.println(name);   //com.draymond.reflect.entity.User
    }

    /**
     * 获取包的路径
     */
    @Test
    public void test3() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Package clazzPackage = clazz.getPackage();
        String packageName = clazzPackage.getName();
        System.out.println(packageName);        //com.draymond.reflect.entity
    }

    /**
     * 获取类的名称
     */
    @Test
    public void test4() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        String simpleName = clazz.getSimpleName();
        System.out.println(simpleName);     // User
    }

    /**
     * 获得当前类继承的父类的名字
     *
     * @throws Exception
     */
    @Test
    public void test5() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Class superclass = clazz.getSuperclass();
        System.out.println(superclass); // class java.lang.Object
    }

    /**
     * 获得当前类实现的类或是接口
     *
     * @throws Exception
     */
    @Test
    public void test6() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Class[] interfaces = clazz.getInterfaces();

        for (Class superclass : interfaces) {
            System.out.println(superclass);     // class java.lang.Object
        }
    }


//-----------------------------   获得类中属性相关的方法   -------------------------------

    /**
     * 获取所有的public修饰的属性
     *
     * @throws Exception
     */
    @Test
    public void test7() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Field[] fields = clazz.getFields();
        System.out.println(fields.length);
        for (Field field : fields) {
            String fieldName = field.getName();
            System.out.println("fieldName==" + fieldName);    //userName

//            boolean aBoolean = field.getBoolean(Integer.class);   //field是String类型,不能转为boolean
//            System.out.println(aBoolean);

            Class<?> type = field.getType();

            String name = type.getName();   // java.lang.String
            System.out.println(name);

        }
    }

    /**
     * 获取所有属性(包括私有)
     *
     * @throws Exception
     */
    @Test
    public void test8() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);          //暴力可见

            String fieldName = field.getName(); //获取属性的名称
            Class<?> type = field.getType();    //获取属性的类型
            String typeName = type.getName();
        }
    }


//-------------------------------  获得类中 Annotation注解 相关的方法 ------------------------

    /**
     * 获取该 类,方法,属性,构造器 上的公有注解对象
     * <p>
     * 获取 User类上标注的 NotBeNull 注解
     *
     * @throws Exception
     */
    @Test
    public void test9() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");

        Annotation annotation = clazz.getAnnotation(NotBeNull.class);   //获取 User类上标注的 NotBeNull 注解
        if (annotation == null) {
            System.out.println("没有从user中获取到 NotBeNull 注解");    // 备注:没有执行(因为User类上加了该注解)
        } else {
            System.out.println("从user中获取到 NotBeNull 注解");       // 从user中获取到 NotBeNull 注解
        }
    }

    /**
     * 返回该 类,方法,属性,构造器 所有的公有注解对象
     *
     * @throws Exception
     */
    @Test
    public void test11() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            Class<? extends Annotation> annotationType = annotation.annotationType();
            String name = annotationType.getName();
            String simpleName = annotationType.getSimpleName();
            System.out.println("name:" + name);             // name:com.draymond.reflect.NotBeNull
            System.out.println("simpleName:" + simpleName); // simpleName:NotBeNull
        }
    }


    /**
     * 获取所有注解(包括非public修饰)
     * 没意义:注解就是public修饰的
     *
     * @throws Exception
     */
    @Test
    public void test12() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations();  //获取
    }

//------------------------------  获得类中构造器相关的方法  ------------------------------

    /**
     * 获取 private 空参构造器
     *
     * @throws Exception
     */
    @Test
    public void test13() throws Exception {

        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Constructor constructor = clazz.getConstructor();   //构造器private
        String constructorName = constructor.getName();
        System.out.println(constructorName);                //  java.lang.NoSuchMethodException: com.draymond.reflect.entity.User.<init>()
    }

    /**
     * 获取 public 实参构造器
     *
     * @throws Exception
     */
    @Test
    public void test14() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Constructor constructor = clazz.getConstructor(Integer.class, String.class, String.class, Integer.class);
        String constructorName = constructor.getName();
        System.out.println(constructorName);    // com.draymond.reflect.entity.User
    }

    /**
     * 获取private 构造器
     *
     * @throws Exception
     */
    @Test
    public void test15() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Constructor declaredConstructor = clazz.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);        //暴力破解
        String constructorName = declaredConstructor.getName();
        System.out.println(constructorName);            // com.draymond.reflect.entity.User
    }

    /**
     * 获得该类所有构造方法
     *
     * @throws Exception
     */
    @Test
    public void test16() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            String constructorName = constructor.getName();
            System.out.println(constructorName);
        }
    }

    //-----------------------  实例化对象 ---------------------------

    /**
     * class不能获取private修饰构造器对应的实例
     *
     * @throws Exception
     */
    @Test
    public void test17() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        User user = (User) clazz.newInstance();  // java.lang.IllegalAccessException: Class com.draymond.reflect.MainTest can not access a member of class com.draymond.reflect.entity.User with modifiers "private"
        System.out.println(user);
    }

    /**
     * 通过构造器获取private修饰构造器对应的实例
     *
     * @throws Exception
     */
    @Test
    public void test18() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Constructor declaredConstructor = clazz.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        User user = (User) declaredConstructor.newInstance();
        System.out.println(user);   // User(id=null, userName=null, sex=null, grade=null, courseList=null)
    }

    /**
     * 通过构造器获取带参构造器对应的实例
     *
     * @throws Exception
     */
    @Test
    public void test19() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Constructor declaredConstructor = clazz.getDeclaredConstructor(Integer.class, String.class, String.class, Integer.class);
        declaredConstructor.setAccessible(true);
        User user = (User) declaredConstructor.newInstance(1, "王老师", "数学", 1);
        System.out.println(user);   // User(id=1, userName=王老师, sex=数学, grade=1, courseList=[])

        // 备注:getDeclaredConstructor()参数的类型与个数 与 newInstance 类型与个数 一致
    }


//-----------------------  获得类中方法相关的方法 ---------------------

    /**
     * 获取所有的方法(包括private)
     *
     * @throws Exception
     */
    @Test
    public void test20() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Method[] methods = clazz.getDeclaredMethods();

        for (Method method : methods) {
            String methodName = method.getName();
            System.out.print(methodName + "  ");  // equals  toString  hashCode  getId  getUserName  canEqual  listAll  setSex  setGrade  getCourseList  setUserName  setCourseList  findById  getSex  getGrade  setId
        }
    }

    /**
     * 获取单个指定方法
     *
     * @throws Exception
     */
    @Test
    public void test21() throws Exception {

        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        // 获取 find 方法,指定参数类型为Integer
        Method methods = clazz.getDeclaredMethod("findById", Integer.class);
        methods.setAccessible(true);
        Constructor constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        User user = (User) constructor.newInstance();

        // 由于 空参构造器是private,所以不能创建实例
        User invoke = (User) methods.invoke(user, 1);
        System.out.println(invoke);
    }

    /**
     * 强行获取私有构造器对象
     *
     * @throws Exception
     */
    @Test
    public void test22() throws Exception {

        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        // 获取 find 方法,指定参数类型为Integer
        Method methods = clazz.getDeclaredMethod("findById", Integer.class);

        Constructor declaredConstructor = clazz.getDeclaredConstructor();
        User user = (User) declaredConstructor.newInstance();
        System.out.println(user);   // User(id=null, userName=null, sex=null, grade=null, courseList=null)

    }

//-------------------------------  类中其他重要的方法  --------------------

    /**
     * 是否为注解
     *
     * @throws Exception
     */
    @Test
    public void test23() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        boolean userIsAnnotation = clazz.isAnnotation();
        System.out.println("userIsAnnotation  :  " + userIsAnnotation);    // false

        Class notBeNullClazz = Class.forName("com.draymond.reflect.NotBeNull");
        boolean notBeNullIsAnnotation = notBeNullClazz.isAnnotation();
        System.out.println("notBeNullIsAnnotation  :  " + notBeNullIsAnnotation);    // true
    }

    /**
     * 指定注解是否存在指定元素上
     *
     * @throws Exception
     */
    @Test
    public void test24() throws Exception {

        Class userClazz = Class.forName("com.draymond.reflect.entity.User");
        boolean annotationPresent = userClazz.isAnnotationPresent(NotBeNull.class);
        System.out.println(annotationPresent);  // true
    }

    /**
     * 是否为匿名类
     *
     * @throws Exception
     */
    @Test
    public void test25() throws Exception {

        AnonymousInterface anonymousInterface = new AnonymousInterface() {
            @Override
            public String print(String msg) {
                System.out.println(msg);
                return msg;
            }
        };
        Class clazz = anonymousInterface.getClass();
        boolean anonymousClass = clazz.isAnonymousClass();
        System.out.println(anonymousClass);     // true

    }

    /**
     * 是否为数组
     *
     * @throws Exception
     */
    @Test
    public void isArray() throws Exception {
        char[] chars = new char[10];

        Class clazz = chars.getClass();
        boolean array = clazz.isArray();
        System.out.println(array);
    }

    /**
     * 是否为 枚举
     *
     * @throws Exception
     */
    @Test
    public void isEnum() throws Exception {
        Class clazz = StatusEnum.class;
        boolean anEnum = clazz.isEnum();
        System.out.println(anEnum); //true
    }

    /**
     * 是否为**的实例
     *
     * @throws Exception
     */
    @Test
    public void isInstance() throws Exception {

        Class clazz = Class.forName("com.draymond.reflect.entity.User");

        User user = new User(1, "zsc", "男", 1);

        boolean instance = clazz.isInstance(user);
        System.out.println(instance);   //true
    }

    /**
     * 是否为接口
     *
     * @throws Exception
     */
    @Test
    public void isInterface() throws Exception {
        Class clazz = AnonymousInterface.class;
        boolean anInterface = clazz.isInterface();
        System.out.println(anInterface);
    }

    /**
     * 是否为局部类
     *
     * @throws Exception
     */
    @Test
    public void isLocalClass() throws Exception {


    }

    /**
     * 是否为内部类
     *
     * @throws Exception
     */
    @Test
    public void isMemberClass() throws Exception {
    }
//-------------------------  Field类  ----------------------------

    /**
     * 属性与obj相等则返回true(obj是属性名,而不是属性类型)
     *
     * @throws Exception
     */
    @Test
    public void test32() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");
        Field userName = clazz.getDeclaredField("userName");
        userName.setAccessible(true);
        boolean isString = userName.equals(String.class);   // false

        boolean isUserName = userName.equals(userName);
        System.out.println(isString);       // false
        System.out.println(isUserName);     // true

    }

    /**
     * get属性值
     *
     * @throws Exception
     */
    @Test
    public void test33() throws Exception {
        Class clazz = Class.forName("com.draymond.reflect.entity.User");

        Constructor constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        User user = (User) constructor.newInstance();
        user.setUserName("draymond");
        Field userName = clazz.getDeclaredField("userName");
        userName.setAccessible(true);
        Object o1 = userName.get(user);
        System.out.println(o1); // draymond
    }

    /**
     * set属性值
     *
     * @throws Exception
     */
    @Test
    public void test34() throws Exception {

        Class clazz = Class.forName("com.draymond.reflect.entity.User");

        Constructor constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        Object o = constructor.newInstance();

        Field userName = clazz.getDeclaredField("userName");
        userName.setAccessible(true);
        userName.set(o, "zsc");

        System.out.println(o);  // User(id=null, userName=zsc, sex=null, grade=null, courseList=null)

    }

    /**
     * 获取注解上的值
     *
     * @throws Exception
     */
    @Test
    public void test35() throws Exception {
        Class clazz = User.class;
        Field userNameField = clazz.getDeclaredField("userName");
        NotBeNull annotation = userNameField.getAnnotation(NotBeNull.class);
        String value = annotation.value();
        System.out.println(value);  //zsc
    }

 

}

 

  注解开发: https://www.cnblogs.com/draymond/p/12499670.html

 5:aop+注解+反射  自动对数据库查询不到的值赋值


    (订单详情页面:订单信息+用户信息 

     单表查订单详情,没有用户信息的;使用代理的方式,自动注入用户信息)


    地址:待续

 
posted @ 2020-03-15 20:40  Draymond  阅读(146)  评论(0编辑  收藏  举报