广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java反射技术详解
  • 364
分享到

Java反射技术详解

2024-04-02 19:04:59 364人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录前言一、基本反射技术1.1 根据一个字符串得到一个类getClass方法Class.forNameType属性二、获取类的成员获取类中特定的构造方法调用构造方法调用类的私有方法获

前言

相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术、Hook技术等必不可少的!

一、基本反射技术

1.1 根据一个字符串得到一个类

getClass方法


 String name = "Huanglinqing";
 Class c1 = name.getClass();
 System.out.println(c1.getName());

打印结果如下:

Class.forName

比如我们获取java.lang.String的类名


   String name = "java.lang.String";
   Class c1 = null;
   try {
          c1 = Class.forName(name);
          System.out.println(c1.getName());
      } catch (ClassNotFoundException e) {
  }

这里也通过捕获异常,因为我们传的这个字符串可能不合法,字符串合法命名是类的命名空间和类的名称组成

打印结果如下:

我们还可以通过c1.getSuperclass()获取到他的父类

Type属性

基本类型都有type属性,可以得到这个基本类型的类型,比如:


Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Float.TYPE;
Class c4 = Double.TYPE;

二、获取类的成员

当类中方法定义为私有的时候我们能调用?不能!当变量是私有的时候我们能获取吗?不能!但是反射可以,比如源码中有你需要用到的方法,但是那个方法是私有的,这个时候你就可以通过反射去执行这个私有方法,并且获取私有变量。

获取类的构造函数

为了便于测试,我们定义一个Test类,Test类如下:(省略get和set方法)

Test类中我们定义是三个私有变量,生成两个公有的含参构造方法和一个私有的含参构造方法以及一个公有的无参构造方法。


public class Test {
    private int age;
    private String name;
    private int testint;
    public Test(int age) {
        this.age = age;
    }
    public Test(int age, String name) {
        this.age = age;
        this.name = name;
    }
    private Test(String name) {
        this.name = name;
    }
    public Test() {
    }

下面我们通过反射获取这些构造方法

获取类的所有构造方法


 Test test = new Test();
 Class c4 = test.getClass();
 Constructor[] constructors ;
 constructors = c4.getDeclaredConstructors();

通过getDeclaredConstructors可以返回类的所有构造方法,返回的是一个数组因为构造方法可能不止一个,通过getModifiers可以得到构造方法的类型,getParameterTypes可以得到构造方法的所有参数,返回的是一个Class数组,所以我们如果想获取所有构造方法以及每个构造方法的参数类型,可以有如下代码:


  for (int i = 0; i < constructors.length; i++) {
        System.out.print(Modifier.toString(constructors[i].getModifiers()) + "参数:");
        Class[] parametertypes = constructors[i].getParameterTypes();
        for (int j = 0; j < parametertypes.length; j++) {
             System.out.print(parametertypes[j].getName() + " ");
       }
      System.out.println("");
  }

运行结果如下所示:

这样我们就得到了类中所有构造方法和构造方法中的参数,那么我们如何获取特定的构造方法呢?

获取类中特定的构造方法

我们可以通过getConstructors方法获取类中 所有的public类型的构造方法,代码和上面一样就不演示了。

我们可以通过getDeclaredConstructor()方法传参获取特定参数类型的构造方法,这里注意是getDeclaredConstructor()不是 getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。

获取无参构造方法直接不传参数,如下所示:


   try {
          constructors = c4.getDeclaredConstructor();
          System.out.print(Modifier.toString(constructors.getModifiers()) + );
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
      }

这里要进行异常捕获,因为可能不存在对应的构造方法,打印结果如下:

如果我们想获取有两个参数分别为int和String类型的构造方法,代码如下:


  Class[] p = {int.class,String.class};
  try {
       constructors = c4.getDeclaredConstructor(p);
       System.out.print(Modifier.toString(constructors.getModifiers()) + "参数:");
       Class[] parametertypes = constructors.getParameterTypes();
       for (int j = 0; j < parametertypes.length; j++) {
            System.out.print(parametertypes[j].getName() + " ");
          }
       } catch (NoSuchMethodException e) {
            e.printStackTrace();
     }

这里我们同样打印出构造方法的参数:

调用构造方法

从这里开始慢慢到了关键的一步,得到类的实例,我们主要借助于newInstance方法,为了方便演示我们将测试类的两个构造方法打印出来.


   public Test(int age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("hello" + name + "i am" + age);
    }
    private Test(String name) {
        this.name = name;
        System.out.println("My Name is" +
                name);
    }

我们先来调用public的方法,如下所示:


 Class[] p = {int.class,String.class};
 constructors = c4.getDeclaredConstructor(p);
 constructors.newInstance(24,"HuangLinqing");

运行打印结果如下:

那么调用私有构造方法呢,和上面一样,只是我们要设置constructors.setAccessible(true);代码如下:


  Class[] p = {String.class};
  constructors = c4.getDeclaredConstructor(p);
  constructors.setAccessible(true);
  constructors.newInstance("HuangLinqing");

打印结果如下:

调用类的私有方法

如何调用类中的私有方法呢,我们先在测试类中编写一个测试的私有方法 如下:


  private void welcome(String tips){
        System.out.println(tips);
    }

我们知道如果我们要正常的调用类的方法都是通过类.方法调用,所以我们调用私有方法也需要得到类的实例,而我们上面newInstace已经得到了类的实例,这样就好办了。


   Class[] p4 = {String.class};
   Method method = c4.getDeclaredMethod("welcome",p4);
   method.setAccessible(true);

我们首先通过 getDeclaredMethod方法获取到这个私有方法,第一个参数是方法名,第二个参数是参数类型

然后通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数。


     Class[] p4 = {String.class};
     Method method = c4.getDeclaredMethod("welcome",p4);
     method.setAccessible(true);
     Object arg1s[] = {"欢迎关注代码男人技术公众号"};
     method.invoke(test,arg1s);

test类的实例当不能new 获取的时候我们也可以通过反射获取,就是上面的newInstance方法。

打印结果如下:

获取类的私有字段并修改值

看到这里你可能会说,有了set方法,什么私有不私有,test.set不就可以了,但是这里要注意我们是没有办法得到这个类的实例的,要不然都可以得到实例就没有反射一说了。我们在通过反射得到类的实例之后先获取字段:


Field field = c4.getDeclaredField("name");
field.setAccessible(true);
field.set(o,"代码男人");

是我们上面通过反射构造方法获取的实例, 打印field.get(o).toString()的值如下:

不过要注意的是我们修改了name的值只对当前的实例对象有效。

Java的基本反射语法就是这样了,欢迎加入技术群一起探讨!

最后反射封装类如下:


package jnidemo.hlq.com.hookdemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Reflex {
    
    public static Object createObject(String className) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};
        try {
            Class r = Class.forName(className);
            return createObject(r, pareTyples, pareVaules);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static Object createObject(Class clazz) {
        Class[] pareTyple = new Class[]{};
        Object[] pareVaules = new Object[]{};
        return createObject(clazz, pareTyple, pareVaules);
    }
    
    public static Object createObject(String className, Class pareTyple, Object pareVaule) {
        Class[] pareTyples = new Class[]{pareTyple};
        Object[] pareVaules = new Object[]{pareVaule};
        try {
            Class r = Class.forName(className);
            return createObject(r, pareTyples, pareVaules);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static Object createObject(Class clazz, Class pareTyple, Object pareVaule) {
        Class[] pareTyples = new Class[]{pareTyple};
        Object[] pareVaules = new Object[]{pareVaule};
        return createObject(clazz, pareTyples, pareVaules);
    }
    
    public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class r = Class.forName(className);
            return createObject(r, pareTyples, pareVaules);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static Object createObject(Class clazz, Class[] pareTyples, Object[] pareVaules) {
        try {
            Constructor ctor = clazz.getDeclaredConstructor(pareTyples);
            ctor.setAccessible(true);
            return ctor.newInstance(pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
        if (obj == null) {
            return null;
        }
        try {
            //调用一个private方法 //在指定类中获取指定的方法
            Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples);
            method.setAccessible(true);
            return method.invoke(obj, pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static Object invokeInstanceMethod(Object obj, String methodName, Class pareTyple, Object pareVaule) {
        Class[] pareTyples = {pareTyple};
        Object[] pareVaules = {pareVaule};
        return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
    }
    
    public static Object invokeInstanceMethod(Object obj, String methodName) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};
        return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
    }
    
    public static Object invokeStaticMethod(String className, String method_name) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};
        return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
    }
    
    public static Object invokeStaticMethod(String className, String method_name, Class pareTyple, Object pareVaule) {
        Class[] pareTyples = new Class[]{pareTyple};
        Object[] pareVaules = new Object[]{pareVaule};
        return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
    }
    
    public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class obj_class = Class.forName(className);
            return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static Object invokeStaticMethod(Class clazz, String method_name) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};
        return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules);
    }
    
    public static Object invokeStaticMethod(Class clazz, String method_name, Class classType, Object pareVaule) {
        Class[] classTypes = new Class[]{classType};
        Object[] pareVaules = new Object[]{pareVaule};
        return invokeStaticMethod(clazz, method_name, classTypes, pareVaules);
    }
    
    public static Object invokeStaticMethod(Class clazz, String method_name, Class[] pareTyples, Object[] pareVaules) {
        try {
            Method method = clazz.getDeclaredMethod(method_name, pareTyples);
            method.setAccessible(true);
            return method.invoke(null, pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static Object getFieldObject(String className, Object obj, String filedName) {
        try {
            Class obj_class = Class.forName(className);
            return getFieldObject(obj_class, obj, filedName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static Object getFieldObject(Class clazz, Object obj, String filedName) {
        try {
            Field field = clazz.getDeclaredField(filedName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static void setFieldObject(Class clazz, Object obj, String filedName, Object filedVaule) {
        try {
            Field field = clazz.getDeclaredField(filedName);
            field.setAccessible(true);
            field.set(obj, filedVaule);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void setFieldObject(String className, Object obj, String filedName, Object filedVaule) {
        try {
            Class obj_class = Class.forName(className);
            setFieldObject(obj_class, obj, filedName, filedVaule);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Object getStaticFieldObject(String className, String filedName) {
        return getFieldObject(className, null, filedName);
    }
    public static Object getStaticFieldObject(Class clazz, String filedName) {
        return getFieldObject(clazz, null, filedName);
    }
    public static void setStaticFieldObject(String classname, String filedName, Object filedVaule) {
        setFieldObject(classname, null, filedName, filedVaule);
    }
    public static void setStaticFieldObject(Class clazz, String filedName, Object filedVaule) {
        setFieldObject(clazz, null, filedName, filedVaule);
    }
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: Java反射技术详解

本文链接: https://www.lsjlt.com/news/156748.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java反射技术详解
    目录前言一、基本反射技术1.1 根据一个字符串得到一个类getClass方法Class.forNameType属性二、获取类的成员获取类中特定的构造方法调用构造方法调用类的私有方法获...
    99+
    2022-11-12
  • java的反射技术详细介绍
    本篇内容主要讲解“java的反射技术详细介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java的反射技术详细介绍”吧!反射的定义:审查元数据并收集关于它的类型信息的能力。下面介绍java的反...
    99+
    2023-06-17
  • 如何理解Java反射技术
    本篇内容介绍了“如何理解Java反射技术”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、前期概要1、 什么是反射Java 反射机制在程序运...
    99+
    2023-06-02
  • Java核心技术之反射
    目录一、Class类与Java反射1、访问构造方法2、访问成员变量3、访问方法二、使用Annotation功能1、定义Annotation类型2、访问Annotation信息总结一、...
    99+
    2022-11-12
  • Java反射技术怎么用
    这篇文章主要为大家展示了“Java反射技术怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java反射技术怎么用”这篇文章吧。一、基本反射技术1.1 根据一个字符串得到一个类getClass...
    99+
    2023-06-25
  • java反射详解(3)
    动态代理 【案例】首先来看看如何获得类加载器:  class test{       } class hello{     public static void main(String[] args) {         test t=ne...
    99+
    2023-01-31
    反射 详解 java
  • Java 反射(Reflect)详解
    目录一 首先我们的去知道什么是反射?二(刨根问底)知道是什么还需要知道什么“成分”组成反射?2.1 Class 对象的获取及使用2.2 拿到碗筷就得去盛饭,拿到了Class就得去操作...
    99+
    2022-11-12
  • Java反射机制详解
    目录类的声明周期不同阶段都可以获取类对象获取Class类对象的方式的场景class类对象的功能如何获取私有变量的值根据有无主方法判断进程和线程反射出现的背景(记住)反射出现的背景类的...
    99+
    2022-11-13
  • java反射技术的使用场景
    这篇文章主要介绍“java反射技术的使用场景”,在日常操作中,相信很多人在java反射技术的使用场景问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java反射技术的使用场景”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-03
  • 【Java 基础篇】Java 反射详解
    文章目录 导言一、反射的概念二、反射的原理三、反射的使用示例四、反射的应用场景五、反射的注意事项总结 导言 Java反射是指在运行时动态地获取类的信息,并可以通过该信息来操作类或对象。...
    99+
    2023-09-14
    java python 开发语言
  • 如何在Java中应用反射技术
    如何在Java中应用反射技术?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、反射概念Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象...
    99+
    2023-06-15
  • java反射超详细讲解
    目录Java反射超详解✌1.反射基础1.1Class类1.2类加载2.反射的使用2.1Class对象的获取2.2Constructor类及其用法2.4Method类及其用...
    99+
    2022-11-12
  • java反射机制最详解
    目录java反射机制什么是反射?反射的功能:反射常用类:1.Class枚举类2.Constructor构造器3.Method方法类4.Field变量类反射运行指示图通过反射获取对象总结java反射机制 什么是反射? 在java开发中有一个...
    99+
    2020-08-07
    java java反射机制
  • 超详细解释Java反射
    目录一、什么是反射1. 反射机制的功能2. 实现反射机制的类二、反射的使用1. Customer类2. ReflectTester类三、具体实例1. ReflexDemo类2. Wr...
    99+
    2022-11-12
  • Java基础之反射详解
    目录前言一、一个需求引出反射二、反射入门三、反射原理图四、反射相关类五、反射调用优化前言 反射是我们框架的灵魂,反射也是我们框架的一个底层基石,没有反射也就没有框架,如果我们学好了反...
    99+
    2022-11-12
  • Java-反射机制(超详解)
    Java反射机制概述 前言一、Java反射机制概述1. Java Reflection2. 动态语言 vs 静态语言 二、 Class类的理解1. 类的加载过程1.1 初步了解1.2 类的加载过程图解1.3 了解:什么时候会发...
    99+
    2023-08-17
    java 开发语言
  • Java反射 PropertyDescriptor类案例详解
    JAVA中反射机制(JavaBean的内省与BeanUtils库) 内省(Introspector) 是Java 语言对JavaBean类属性、事件的一种缺省处理方法。 JavaB...
    99+
    2022-11-12
  • Java反射机制基础详解
    目录1、什么是Java反射机制?2、反射机制原理3、Class类介绍3.1、Class类基本介绍3.2、Class类对象的获取方法Class.forname()3.3、可以获取Cla...
    99+
    2022-11-12
  • Java中的反射机制详解
    目录一、什么是反射?二、为什么要用反射三、Class类四、获取Class类对象的四种方式五.通过反射构造一个类的实例①使用Class.newInstance②通过反射先获取构造方法再...
    99+
    2022-11-12
  • 详解Java反射创建对象
    一、什么是反射 Java Reflaction in Action中的解释:反射是运行中的程序检查自己和软件运行环境的能力,它可以根据它发现的进行改变。通俗的讲就是反射可以在运行时根...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作