• 十四.java反射机制


    1.反射是Java提供的一种运行机制,代码运行时动态的获取一个类型的各种信息,以及相关的一系列操作

      Java中每一种类型,都有且仅有一个Class对象与之对应,每种类型在进行类加载之后,JVM会在内存中自动生成一个Class类型对象

      Student.java---->Student.class--->类加载--->成功----->内存中产生Class类型对象

    2.反射中重要的类和包:反射机制中的常见类的含义

      java.lang包下:
        Class 类 对java中所有类型抽象而得来的
        package类 对java中所有包抽象而得来的

      java.lang.reflect包下:
        Modifier 类 对java中所有修饰符抽象而得来的
        Field 类 对java中所有属性抽象而得来的
        Method 类 对java中所有方法抽象而得来的
        Constructor 类 对java中所有构造器抽象而得来的
        Array 类 提供了对数组对象的动态访问
        ParameterizedType 接口 在反射中表示参数化类型
          例如:List<String> Point<Long,Long>等这种带泛型的类型

    3.获得一个类类型的Class对象的三种方式

      以上几种情况中,所以最多的还是类类型的Class对象

        1.使用对象调用getClass方法获得
          getClass是Object中的final修饰的方法,每个对象都可以调用而且不能重写
          Student s = new Student();
          Class c = s.getClass();

        2.使用类名获得
          Class c = Student.class;

        3.使用Class类中的forName方法获得
          //这种方法很灵活,只需一个String类型参数即可
          //而String类型的数据改变起来很容易
          //注意该方法是会抛出异常的
          Class c = Class.forName("com.briup.test.Student");

        注:以上三种方法获得的同一个对象(==比较),因为每个类型内存都有且只有一个Class类型对象

    4.创建任意类的对象

      public Object test(String className){
        Class<?> c=Class.forName(className);
        Object obj = c.newInstance();
        return obj;
      }

      注:在开发中要保证无参构造器的存在,否则在反射的时候会很麻烦。

    5.使用Class类型对象获得类中的信息

      1.获得该类所处的包的信息
        Student s = new Student();
        Class c = s.getClass();
        System.out.println(c.getPackage().getName());

      2.获得该类的修饰符信息
        //每个修饰符对应一个int值
        //如果有多个修饰符则int值相加
        Student s = new Student();
        Class c = s.getClass();
        System.out.println(c.getModifiers());

        这里涉及到Modifier这个类,这个类中定义了一系列的修饰符所对应的值

      3.获得该类的全限定类名
        Student s = new Student();
        Class c = s.getClass();
        System.out.println(c.getName());

      4.获得该类的父类的Class对象

        Student s = new Student();
        Class c = s.getClass();
        //superclass表示其父类型的Class对象
        Class superclass = c.getSuperclass();
        System.out.println(superclass.getName());

        例如:
          Class c = Object.class;
          Class superclass = c.getSuperclass();
          System.out.println(superclass.getName());
          //运行报错,因为Object没有父类

        例如:
          //判断c1是不是c2的子类型
          //判断c3是不是c2的子类型
          Class c1 = Student.class;
          Class c2 = Person.class;
          Class c3 = String.class
          System.out.println(c2.isAssignableFrom(c1));//true
          System.out.println(c2.isAssignableFrom(c3));//false

      5.获得该类所实现的接口类型的Class对象

        Student s = new Student();
        Class c = s.getClass();
        Class[] interfaces = c.getInterfaces();
        for(Class clazz:interfaces){
          System.out.println(clazz.getName());
        }
        例如:
          //判断c1是不是c2的实现类
          //判断c3是不是c2的实现类
          Class c1 = Student.class;
          Class c2 = Action.class;
          Class c3 = String.class
          System.out.println(c2.isAssignableFrom(c1));//true
          System.out.println(c2.isAssignableFrom(c3));//false

      6.获得该类中所有的属性

        Student s = new Student();
        Class c = s.getClass();
        Field[] declaredFields = c.getDeclaredFields();
        for(Field f:declaredFields){
          System.out.println(f.getModifiers());
          System.out.println(f.getType().getName());
          System.out.println(f.getName());
        }
        注:
          getDeclaredFields()方法返回类中声明的属性,包括私有的
          getFields()方法只返回类中public修饰的属性,包括继承的
        例如:
          //获得某个指定的属性(也包括私有属性)
          Student s = new Student();
          Class c = s.getClass();
          Field f = c.getDeclaredField("score");
          System.out.println(f.getModifiers());
          System.out.println(f.getType().getName());
          System.out.println(f.getName());

      7.获得该类中所有的方法

        Student s = new Student();
        Class c = s.getClass();
        Method[] declaredMethods = c.getDeclaredMethods();
        for(Method m:declaredMethods){
          System.out.println(m.getModifiers());
          System.out.println(m.getReturnType().getName());
          System.out.println(m.getName());
          System.out.println(Arrays.toString(m.getParameterTypes()));
          System.out.println(Arrays.toString(m.getExceptionTypes()));
        }

        注:
          getDeclaredMethods()方法返回类中声明的方法,包括私有的
          getMethods()方法只返回类中public修饰的方法,包括继承的

        例如:
          //获得某个指定的方法(也包括私有方法)
          Student s = new Student();
          Class c = s.getClass();
          Method m = c.getDeclaredMethod("print");
          System.out.println(m.getModifiers());
          System.out.println(m.getReturnType().getName());
          System.out.println(m.getName());
          System.out.println(Arrays.toString(m.getParameterTypes()));
          System.out.println(Arrays.toString(m.getExceptionTypes()));

        注:反射重载方法会报出:java.lang.NoSuchMethodException: java.lang.String.valueOf()

      8.获得该类中所有的构造器

        Student s = new Student();
        Class c = s.getClass();
        Constructor[] declaredConstructors = c.getDeclaredConstructors();
        for(Constructor con:declaredConstructors){
          System.out.println(con.getModifiers());
          System.out.println(con.getName());
          System.out.println(Arrays.toString(con.getParameterTypes()));
          System.out.println(Arrays.toString(con.getExceptionTypes()));
        }

        注:
          getDeclaredConstructors()方法返回类中所有构造器
          getConstructors()方法只返回类中public修饰的构造器

        例如:
          //获得某个指定的构造器(也包括私有构造器)
          Student s = new Student();
          Class c = s.getClass();
          Constructor con = c.getDeclaredConstructor(double.class);
          System.out.println(con.getModifiers());
          System.out.println(con.getName());
          System.out.println(Arrays.toString(con.getParameterTypes()));
          System.out.println(Arrays.toString(con.getExceptionTypes()));

      9.获得父类型中的泛型的真实类型:麻烦 略……

      10.获得类中的注解:使用反射也可以获得类中的注解,我在开发时没用过,略……

  • 相关阅读:
    JVM基础
    JVM基础
    python相关
    charles 的配置与使用
    大型缓存架构实战
    redis环境搭建
    多线程与并发 | 线程池
    JVM | 内存溢出和解决方案
    读书笔记 | Mysql是怎样运行的
    读书笔记 | Java并发编程实战
  • 原文地址:https://www.cnblogs.com/Magic-Li/p/12813537.html
Copyright © 2020-2023  润新知