重识JAVA基础-反射

反射

反射是框架设计的灵魂

(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

一、反射的概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

以上的总结就是什么是反射
反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
如图是类的正常加载过程:反射的原理在与class对象。
熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象

image-20220903163722619

其中这个Class对象很特殊。我们先了解一下这个C lass类

他有很多方法

image-20220903163844003

二、反射的应用

  • Reflection(反射) 是被视为动态语言的关键,反射机制允许程序在执行期借
  • 助于ReflectionAPI获取任何类的内部信息,并能直接操作对象的内部属性和方法。
  • java.lang.Class:代表一个类
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造方法
public class Student  {
    private int age;
    private String name;
    
    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

先来创建一个student类

Class<Student> clazz = Student.class;
Constructor<Student> constructor = clazz.getConstructor(int.class, int.class, String.class);
Student student = constructor.newInstance(10, 23, "王冰");
System.out.println(student);

通过这个实例我们知道了获取类的Class类很重要

获取Class

方式一:调用运行时类的属性:.class
Class clazz = Student.class;
System.out.println(clazz);

方式二:通过运行时类的对象
Student student = new Student();
Class clazz2 = student.getClass();
System.out.println(clazz2);

方式三:通过Class的静态方法forName(String classPath)
Class clazz3 = Class.forName(“a05.Student”);
System.out.println(clazz3);

方式四:使用类加载器:classLoader
ClassLoader classLoader = ReflectionDemo1.class.getClassLoader();
Class clazz4 = classLoader.loadClass(“a05.Student”);
System.out.println(clazz4);

类加载器

类加载器
作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区运行时的数据结构,
然后在堆生成一个代表这个类的Class文件,作为方法区类数据的入口
类缓存:一个类被加载到类加载器会缓存一段时间

@Test
public void test1(){
    //自定义类,使用系统类加载器器
    ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
    //Launcher$AppClassLoader
    System.out.println(classLoader);
    //通过系统类加载器getParent获取扩展类加载器
    ClassLoader parent = classLoader.getParent();
    //Launcher$ExtClassLoader
    System.out.println(parent);
    //引导类加载器主要负责java的核心类库,无法加载自定义类的
    ClassLoader parent1 = parent.getParent();
    System.out.println(parent1);
    //String是引导类加载器加载的,无法获取
    ClassLoader classLoader1 = String.class.getClassLoader();
    System.out.println(classLoader1);
}

image-20220903165430146

运行时类

@Test
public void test1() {
    Class<Student> clazz = Student.class;
    //获取声明为public
    Constructor<?>[] constructors = clazz.getConstructors();
    for (Constructor<?> constructor : constructors) {
        System.out.println(constructor.getName());
    }
    Constructor<?>[] declaredClasses = clazz.getDeclaredConstructors();
    for (Constructor<?> constructor1 : declaredClasses) {
        System.out.println(constructor1);
    }
}

//获取运行时类的父类
@Test
public void test2() {
    Class<Student> clazz = Student.class;
    System.out.println(clazz.getSuperclass().getName());
    //带泛型的父类
    Type genericSuperclass = clazz.getGenericSuperclass();
    System.out.println(genericSuperclass);
}

//获取运行时类实现的接口
@Test
public void test3() {
    Class<Student> clazz = Student.class;
    Class<?>[] interfaces = clazz.getInterfaces();
    for (Class c : interfaces) {
        System.out.println(c);
    }
    //获取带泛型的
    Type[] genericInterfaces = clazz.getGenericInterfaces();
    for (Type t : genericInterfaces) {
        System.out.println(t);
    }
}

//获取运行时类所在的包
@Test
public void test4() {
    Class<Student> aClass = Student.class;
    Package aPackage = aClass.getPackage();
    System.out.println(aPackage);
}

//获取运行时类的注解
@Test
public void test5() {
    Class<Student> aClass = Student.class;
    Annotation[] annotations = aClass.getAnnotations();
    for (Annotation a : annotations) {
        System.out.println(a);
    }

}

创建一个指定类的对象

@Test
public void test2() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    int i = new Random().nextInt(3);
    String classPath = "";
    switch (i) {
        case 0:
            classPath = "java.util.Date";
            break;
        case 1:
            classPath = "java.lang.Object";
            break;
        case 2:
            classPath = "a05.Student";
            break;
    }
    Object clazz = getInstance(classPath);
    System.out.println(clazz);
}

//创建一个指定类的对象
public static Object getInstance(String classPath) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    Class<?> aClass = Class.forName(classPath);
    return aClass.newInstance();
}

通过反射设置属性

@Test
public void test0() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
    Class<Student> studentClass = Student.class;
    Student student = studentClass.newInstance();
    Field age = studentClass.getDeclaredField("age");
    age.setAccessible(true);
    age.set(student, 19);
    System.out.println(student);
}

通过反射调用方法

@Test
public void test1() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
    Class<Student> studentClass = Student.class;
    Student student = studentClass.newInstance();
    //获取指定的属性
    //方法名字,参数1,参数2
    Method display = studentClass.getDeclaredMethod("display", String.class);
    //private set一下
    display.setAccessible(true);
    //调用:参数1:方法调用者 参数2赋值的形参
    display.invoke(student, "王冰");
}

通过反射调用构造器

@Test
public void test2() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class<Student> studentClass = Student.class;
    Student student = studentClass.newInstance();
    //1.获取指定的构造器
    Constructor<Student> declaredConstructor = studentClass.getDeclaredConstructor(int.class, int.class, String.class);
    Student wangbing = declaredConstructor.newInstance(19, 20, "王冰");
    System.out.println(wangbing);
}

版权声明:本文为weixin_53227758原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。