目录
反射
反射定义
反射的基本运用
1. 获取类对象
a. forName()方法
b. 直接获取
c. getClass()方法
d. getSystemClassLoader().loadClass()方法
2. 获取类方法
a. getDeclaredMethods
b. getDeclaredMethod
c. getMethods
d. getMethod
3. 获取成员变量
a. getDeclaredFields
b. getDeclaredField(String name)
c. getFields()
d. getField(String name)
4. 获取构造函数Constructor
5. 反射创建类对象
newInstance
invoke
Runtime的rce例子(访问限制突破)
后记
首页 Java java教程 Java反射的使用方法及示例分析

Java反射的使用方法及示例分析

May 06, 2023 pm 04:31 PM
java

    反射

    反射定义

    对象可以通过反射获取他的类,类可以通过反射拿到所有⽅法(包括私有) 通过java语言中的反射机制可以操作字节码文件,可以读和修改字节码文件

    反射的基本运用

    1. 获取类对象

    a. forName()方法

    只需要知道类名,在加载JDBC的时候会采用 实例代码

    public class test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            Class name = Class.forName("java.lang.Runtime");
            System.out.println(name);
        }
    }
    登录后复制

    Java反射的运用方法实例分析

    b. 直接获取

    使用.class去获取对于的对象

    public class test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> name = Runtime.class;
            System.out.println(name);
        }
    }
    登录后复制
    c. getClass()方法

    getClass来获取字节码对象,必须要明确具体的类,然后创建对象

    public class test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            Runtime rt = Runtime.getRuntime();
            Class<?> name = rt.getClass();
            System.out.println(name);
        }
    }
    登录后复制
    d. getSystemClassLoader().loadClass()方法

    这个方法和forName类似,只要有类名就可以了,但是区别在于,forName的静态JVM会装载类,并执行static()中的代码

    public class getSystemClassLoader {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> name = ClassLoader.getSystemClassLoader().loadClass("java.lang.Runtime");
            System.out.println(name);
        }
    }
    登录后复制

    2. 获取类方法

    a. getDeclaredMethods

    返回类或接口声明的所有方法,包括public、protected、private和默认方法,但是不包括继承的方法

    import java.lang.reflect.Method;
    
    public class getDeclaredMethods {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> name = Class.forName("java.lang.Runtime");
            System.out.println(name);
            Method[] m = name.getDeclaredMethods();
            for(Method x:m)
                System.out.println(x);
        }
    }
    登录后复制

    Java反射的运用方法实例分析

    b. getDeclaredMethod

    获取特定的方法,第一个参数是方法名,第二个参数是该方法的参数对应的class对象,例如这里Runtime的exec方法参数为一个String,所以这里的第二个参数是String.class

    import java.lang.reflect.Method;
    
    public class getDeclaredMethod {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
            Class<?> name = Class.forName("java.lang.Runtime");
            Method m = name.getDeclaredMethod("exec",String.class);
            System.out.println(m);
        }
    }
    登录后复制
    c. getMethods

    返回某个类所有的public方法,包括继承类的public方法

    d. getMethod

    参数同理getDeclaredMethod

    3. 获取成员变量

    同理Method的那几个方法

    a. getDeclaredFields

    获取类的成员的所有变量数组,但是不包括父类的

    b. getDeclaredField(String name)

    获取特定的,参数是想要的方法的名称

    c. getFields()

    同理,只能获得public的,但是包括了父类的

    d. getField(String name)

    同理,参数是想要的方法的名称

    4. 获取构造函数Constructor

    Constructor[] getConstructors() :只返回public构造函数

    Constructor[] getDeclaredConstructors() :返回所有构造函数

    Constructor<> getConstructor(类... parameterTypes) : 匹配和参数配型相符的public构造函数

    Constructor<> getDeclaredConstructor(类... parameterTypes) : 匹配和参数配型相符的构造函数

    后面两个方法的参数是对于方法的参数的类型的class对象,和Method的那个类似,例如String.class

    5. 反射创建类对象

    newInstance

    可以通过反射来生成实例化对象,一般我们使用Class对象的newInstance()方法来进行创建类对象

    创建的方法就是:只需要通过forname方法获取到的class对象中进行newInstance方法创建即可

    Class c = Class.forName("com.reflect.MethodTest"); // 创建Class对象
    Object m1 =  c.newInstance(); // 创建类对象
    登录后复制
    invoke

    invoke方法位于java.lang.reflect.Method类中,用于执行某个的对象的目标方法,一般会和getMethod方法配合进行调用。

    使用用法:

    public Object invoke(Object obj, Object... args)
    登录后复制

    第一个参数为类的实例,第二个参数为相应函数中的参数

    obj:从中调用底层方法的对象,必须是实例化对象

    args: 用于方法的调用,是一个object的数组,参数有可能是多个

    但需要注意的是,invoke方法第一个参数并不是固定的:

    • 如果调用这个方法是普通方法,第一个参数就是类对象;

    • 如果调用这个方法是静态方法,第一个参数就是类;

    通过一个例子去理解

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Invoke {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
            Class c = Class.forName("Invoke");
            Object o = c.newInstance();
            Method m = c.getMethod("test");
            m.invoke(o);
        }
        public void test(){
            System.out.println("测试成功");
        }
    }
    登录后复制

    Java反射的运用方法实例分析

    简单来说就是这样

    方法.invoke(类或类对象)

    先forName拿到Class,再newInstance获取类对象,再getMethod获取方法,然后调用

    Runtime的rce例子(访问限制突破)

    Runtime类里面有一个exec方法,可以执行命令

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Exec {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
            Class c = Class.forName("java.lang.Runtime");
            Object o = c.newInstance();
            Method m = c.getMethod("exec",String.class);
            m.invoke(o,"/System/Applications/Calculator.app/Contents/MacOS/Calculator");
        }
    }
    登录后复制

    但是发现报错了

    Java反射的运用方法实例分析

    出现这个问题的原因:

    • 使用的类没有无参构造函数

    • 使用的类构造函数是私有的

    那么解决方案就是setAccessible(true);,用这个去突破访问限制

    Java.lang.reflect.AccessibleObject类是Field,Method和Constructor类对象的基类,可以提供将反射对象标记为使用它抑制摸人Java访问控制检查的功能,同时上述的反射类中的Field,Method和Constructor继承自AccessibleObject。所以我们在这些类方法基础上调用setAccessible()方法,既可对这些私有字段进行操作

    简单来说,私有的属性、方法、构造方法,可以通过这个去突破限制,xxx.setAccessible(true) 可以看到Runtime的构造方法是private的

    Java反射的运用方法实例分析

    那么这里我们就可以这么去突破限制 先获取构造方法,然后setAccessible获取访问权限 然后再最后invoke里面,第一个参数写成con.newInstance()

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Exec {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
            Class c = Class.forName("java.lang.Runtime");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Method m = c.getMethod("exec",String.class);
            m.invoke(con.newInstance(),"/System/Applications/Calculator.app/Contents/MacOS/Calculator");
        }
    }
    登录后复制

    Java反射的运用方法实例分析

    这里有一个疑问,如果把con.newInstance单独提取出来,他打开计算器不会显示出来,但是后台的确是启动了,不知道啥原因

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Exec {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
            Class c = Class.forName("java.lang.Runtime");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object o = con.newInstance();
            Method m = c.getMethod("exec",String.class);
            m.invoke(o,"/System/Applications/Calculator.app/Contents/MacOS/Calculator");
        }
    }
    登录后复制

    后记

    反射中常用的几个重要方法:

    • 获取类的⽅法: forName

    • 实例化类对象的⽅法: newInstance

    • 获取函数的⽅法: getMethod

    • 执⾏函数的⽅法: invoke

    • 限制突破方法:setAccessible

    以上是Java反射的使用方法及示例分析的详细内容。更多信息请关注PHP中文网其他相关文章!

    本站声明
    本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

    热AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智能驱动的应用程序,用于创建逼真的裸体照片

    AI Clothes Remover

    AI Clothes Remover

    用于从照片中去除衣服的在线人工智能工具。

    Undress AI Tool

    Undress AI Tool

    免费脱衣服图片

    Clothoff.io

    Clothoff.io

    AI脱衣机

    AI Hentai Generator

    AI Hentai Generator

    免费生成ai无尽的。

    热门文章

    R.E.P.O.能量晶体解释及其做什么(黄色晶体)
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳图形设置
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您听不到任何人,如何修复音频
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.聊天命令以及如何使用它们
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

    热工具

    记事本++7.3.1

    记事本++7.3.1

    好用且免费的代码编辑器

    SublimeText3汉化版

    SublimeText3汉化版

    中文版,非常好用

    禅工作室 13.0.1

    禅工作室 13.0.1

    功能强大的PHP集成开发环境

    Dreamweaver CS6

    Dreamweaver CS6

    视觉化网页开发工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神级代码编辑软件(SublimeText3)

    Java 中的完美数 Java 中的完美数 Aug 30, 2024 pm 04:28 PM

    Java 完美数指南。这里我们讨论定义,如何在 Java 中检查完美数?,示例和代码实现。

    Java 中的随机数生成器 Java 中的随机数生成器 Aug 30, 2024 pm 04:27 PM

    Java 随机数生成器指南。在这里,我们通过示例讨论 Java 中的函数,并通过示例讨论两个不同的生成器。

    Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

    Java 版 Weka 指南。这里我们通过示例讨论简介、如何使用weka java、平台类型和优点。

    Java 中的史密斯数 Java 中的史密斯数 Aug 30, 2024 pm 04:28 PM

    Java 史密斯数指南。这里我们讨论定义,如何在Java中检查史密斯号?带有代码实现的示例。

    Java Spring 面试题 Java Spring 面试题 Aug 30, 2024 pm 04:29 PM

    在本文中,我们保留了最常被问到的 Java Spring 面试问题及其详细答案。这样你就可以顺利通过面试。

    突破或从Java 8流返回? 突破或从Java 8流返回? Feb 07, 2025 pm 12:09 PM

    Java 8引入了Stream API,提供了一种强大且表达力丰富的处理数据集合的方式。然而,使用Stream时,一个常见问题是:如何从forEach操作中中断或返回? 传统循环允许提前中断或返回,但Stream的forEach方法并不直接支持这种方式。本文将解释原因,并探讨在Stream处理系统中实现提前终止的替代方法。 延伸阅读: Java Stream API改进 理解Stream forEach forEach方法是一个终端操作,它对Stream中的每个元素执行一个操作。它的设计意图是处

    Java 中的时间戳至今 Java 中的时间戳至今 Aug 30, 2024 pm 04:28 PM

    Java 中的时间戳到日期指南。这里我们还结合示例讨论了介绍以及如何在java中将时间戳转换为日期。

    Java程序查找胶囊的体积 Java程序查找胶囊的体积 Feb 07, 2025 am 11:37 AM

    胶囊是一种三维几何图形,由一个圆柱体和两端各一个半球体组成。胶囊的体积可以通过将圆柱体的体积和两端半球体的体积相加来计算。本教程将讨论如何使用不同的方法在Java中计算给定胶囊的体积。 胶囊体积公式 胶囊体积的公式如下: 胶囊体积 = 圆柱体体积 两个半球体体积 其中, r: 半球体的半径。 h: 圆柱体的高度(不包括半球体)。 例子 1 输入 半径 = 5 单位 高度 = 10 单位 输出 体积 = 1570.8 立方单位 解释 使用公式计算体积: 体积 = π × r2 × h (4

    See all articles