Java反射---Class对象,获得类的方法、成员变量和构造函数信息

Java 中的内置的类加载器

  • Bootstrap class loader:它是虚拟机的内置类加载器,通常表示为null ,并且没有父null

  • Platform class loader:平台类加载器可以看到所有平台类 ,平台类包括由平台类加载器或其祖先定义的Java SE平台API,其实现类和JDK特定的运行时类

  • System class loader:它也被称为应用程序类加载器 ,与平台类加载器不同。 系统类加载器通常用于定义应用程序类路径,模块路径和JDK特定工具上的类

  • 类加载器的继承关系:System的父加载器为Platform,而Platform的父加载器为Bootstrap

  • java.lang.ClassLoader

方法名说明
static ClassLoader getSystemClassLoader()返回用于委派的系统类加载器
ClassLoader getParent()返回父类加载器进行委派
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);      
// sun.misc.Launcher$AppClassLoader@18b4aac2

ClassLoader parentLoader = systemClassLoader.getParent();
System.out.println(parentLoader);           
// sun.misc.Launcher$ExtClassLoader@1540e19d

ClassLoader rootLoad = parentLoader.getParent();
System.out.println(rootLoad);               
// null

反射

三种方式获得Class对象

  • 类名.class属性

    • Class c1 = Foo.class
  • 对象名.getClass()

    • Class c2 = foo.getClass()
  • Class.forName(全类名) , 动态加载类

    • Class c3 = Class.forName("test.reflect.Foo")
  • 三者是相等的

    • System.out.println(c1 == c2&&c2 == c3)
  • 通过Class类的对象获得某个类的信息

    • getName() 返回类类型的名称
    • getSimpleName() 返回类类型的名称的简写
    java.lang.String    // getName()
    String              // getSimpleName()
    
    Class c1 = int.class;
    Class c2 = String.class;
    Class c3 = void.class;
    Class c4 = double.class;
    Class c5 = Double.class;
    System.out.println(c1.getName());
    System.out.println(c2.getName());
    System.out.println(c3.getName());
    System.out.println(c4.getName());
    System.out.println(c5.getName());

#   int
#   java.lang.String
#   void
#   double
#   java.lang.Double

获取构造函数

方法名说明
Constructor<?>[] getConstructors()返回所有public构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor getConstructor(Class<?>… parameterTypes)返回单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造方法对象
  • T newInstance(Object...initargs) 根据指定的构造方法创建对象

  • 调用共有的构造方法创建对象

    public static void main(String[] args) {
        try {
            Class<?> studentClass = Class.forName("main.language.StudentReflect");
            Constructor<?> constructor = studentClass.getDeclaredConstructor(String.class, int.class, String.class);
            Object obj = constructor.newInstance("张三", 20, "合肥");
            System.out.println(obj);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    
  • 使用私有构造函数创建对象。需要先设置访问权限setAccessible

    // 获得一个私有的构造方法
    Constructor<?> privateCons = studentClass.getDeclaredConstructor(String.class);
    privateCons.setAccessible(true);    // 调用私有方法需要先修改访问权限
    Object obj2 = privateCons.newInstance("李四");
    System.out.println(obj2);
    

获得成员变量

方法名说明
Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象
void set(Object obj, Object value)给obj对象的成员变量赋值为value
getType()获得 变量的类型。返回Class
    Field nameField = studentClass.getDeclaredField("name");
    nameField.setAccessible(true);
    nameField.set(obj2, "李斯");
    System.out.println(obj2);

获得成员方法

方法也是对象,一个成员方法就是一个Method对象实例

方法名说明
Method[] getMethods()返回所有public成员方法对象的数组,包括继承
Method[] getDeclaredMethods()返回所有(public, protected, default)成员方法对象的数组,不包括继承
Method getMethod(String name, Class<?>…parameterTypes)返回单个public成员方法对象,包括继承
Method getDeclaredMethod(String name, Class<?>…parameterTypes)返回单个(public,protected,private)成员方法对象 ,不包括继承
Object invoke(Object obj, Object… args)调用obj对象的成员方法,参数是args,返回值是Object类型
getReturnType()获得返回值,返回的是 Class
    Method method1 = studentClass.getMethod("method1");
    Method method3 = studentClass.getMethod("method3", String.class, int.class);
    Method function = studentClass.getDeclaredMethod("function");
    function.setAccessible(true);

    method1.invoke(obj2);
    method3.invoke(obj2, "方法三", 100);
    function.invoke(obj2);
  • 绕过泛型类型检查
    // 绕过泛型检查
    ArrayList<Integer> list = new ArrayList<>();
    Class<? extends ArrayList> listClass = list.getClass();
    Method addMethod = listClass.getMethod("add", Object.class);
    addMethod.invoke(list, "aaaaa");
    addMethod.invoke(list, "bbbbb");
    addMethod.invoke(list, "ccccc");
    
//  String res1 = list.get(0);              // 编译错误
//  Integer res2 = list.get(0);             // 类型转换错误
    System.out.println(list.get(0));        // 正常
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值