首页 > 编程语言 >Java反射

Java反射

时间:2024-10-09 09:45:06浏览次数:10  
标签:反射 Java String System public println Class out

Java反射

参考文章:

JAVA反序列化 - 反射机制

Java反射(超详细!)

Java反射(简单详细且易懂,快速入门)

0 准备一个User类

package org.example.reflect;

public class User {
    public String name;
    private int age;

    public User(){}

    private User(String name){
        this.name = name;
    }

    public User(String name, int age){
        this.name = name;
        this.age = age;
    }

    private void testPrivate(String name, int age){
        System.out.println("这是一个用来测试的私有方法。User [name=\"+ name +\", age=\"+age+\"]");
    }

    public void testPublic(String name, int age) {
        System.out.println("这是一个用来测试的公有方法。User [name=\"+ name +\", age=\"+age+\"]");
    }

    public String toString(){
        return "User [name="+ name +", age="+age+"]";
    }
}

1 反射相关类

含义
java.lang.Class 代表整个字节码;代表一个类型,代表整个类
java.lang.reflect.Constructor 代表字节码中的构造方法字节码;代表类中的构造方法
java.lang.reflect.Field 代表字节码中的属性字节码;代表类中的成员变量(静态变量+实例变量)
java.lang.reflect.Method 代表字节码中的方法字节码;代表类中的方法

通常是先获取Class类,再通过Class类的方法获取Method类、Constructor类或Field类

2 获取Class类

  • Class.forName("类的静态路径")
  • 类名.Class
  • 对象名.getClass()
package org.example.reflect;

public class ReflectTest01 {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

        Class<?> c1 = Class.forName("org.example.reflect.User");
        //如果无参构造函数是private,则无法使用newInstance方法
        //Object o1 = c1.newInstance();
        System.out.println(c1.getName());

        Class<?> c2 = User.class;
        //Object o2 = c2.newInstance();
        System.out.println(c2.getName());

        User user = new User("zhangsan",18);
        Class<? extends User> c3 = user.getClass();
        Object o3 = c3.newInstance();
        System.out.println(o3);
    }
}

获取到Class类后,可以通过如下方法获取对应的构造函数、成员方法或者成员变量才进行其它操作

通过Class获取Constructor

方法 含义
public Constructor getConstructor(Class<?>... parameterTypes) 获取公开的构造方法
public Constructor<?>[] getConstructors() 获取所有的公开的构造方法
public Constructor getDeclaredConstructor(Class<?>... parameterTypes) 获取指定包括私有,不包括继承的Constructor对象
public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法,包括私有

通过Class获取Field

方法 含义
public Field getField(String name) 获取指定公共属性的Field对象
public Field[] getFields() 获取所有公开的成员变量,包括继承变量
public Field getDeclaredField(String name) 获取指定包括私有,不包括继承的Field对象
public Field[] getDeclaredFields() 获取本类定义的成员变量,包括私有,但不包括继承的变量

通过Class获取Method

方法 含义
public Method getMethod(String name, Class<?>... parameterTypes) 获取指定方法的Method对象
public Method[] getMethods() 获取所有可见的方法,包括继承的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取指定包括私有,不包括继承的Method对象
public Method[] getDeclaredMethods() 获取本类定义的的方法,包括私有,不包括继承的方法

3 获取Constructor

package org.example.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectTest02 {
    public static void main(String[] args) {
        Class<?> userClass = User.class;

        //测试getConstructors()函数
        Constructor<?>[] constructors = userClass.getConstructors();
        System.out.println("\n通过getConstructors()获取所有公开构造方法");
        for (Constructor<?> con : constructors) {
            System.out.println("构造方法名称为:" + con.getName());
            Class<?>[] paramList = con.getParameterTypes();
            System.out.println("参数数量为:" + paramList.length);
            System.out.println("形参类型为:");
            for (Class<?> p : paramList) {
                System.out.println(p);
            }
        }
        System.out.println();//换行

        //测试getDeclaredConstructors()函数
        Constructor<?>[] DeclaredConstructors = userClass.getDeclaredConstructors();
        System.out.println("\n通过getDeclaredConstructors()获取所有构造方法(包括私有,包括继承)");
        for (Constructor<?> con : DeclaredConstructors) {
            System.out.println("构造方法名称为:" + con.getName());
            Class<?>[] paramList = con.getParameterTypes();
            System.out.println("参数数量为:" + paramList.length);
            System.out.println("形参类型为:");
            for (Class<?> p : paramList) {
                System.out.println(p);
            }
        }

        //测试getConstructor()函数
        try {
            Constructor<?> constructor = userClass.getConstructor(String.class, int.class);
            Object o = constructor.newInstance("Alice",18);
            System.out.println("\n构造的对象为:" + o);
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

4 获取Field

package org.example.reflect;

import java.lang.reflect.Field;

public class ReflectTest03 {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        Class<User> userClass = User.class;
        Object o = userClass.newInstance();

        //测试getFields()函数
        Field []studentFields = userClass.getFields();
        System.out.println("\n通过getFields获取Student类所有公开属性");
        for (Field field:studentFields) {
            System.out.println("属性的类型为:"+field.getType()+"属性的名称为:"+field.getName());
        }

        //测试getDeclaredFields()函数
        Field []studentDeclaredFields = userClass.getDeclaredFields();
        System.out.println("\n通过getDeclaredFields获取Student类所有属性(包括私有,不包括继承)");
        for (Field field :studentDeclaredFields) {
            System.out.println("属性的类型为:"+field.getType()+"\t属性的名称为:"+field.getName());
        }

        //测试getField(String)函数
        try {
            Field field = userClass.getField("name");
            System.out.println("\n通过getField(\"name\")获取公开属性name");
            System.out.println("属性的类型为:"+field.getType()+"\t属性的名称为:"+field.getName());
            field.set(o,"Bob");
            System.out.println(o);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }

        //测试getDeclaredField(String)函数
        try {
            Field declaredFiled = userClass.getDeclaredField("age");
            System.out.println("\n通过getDeclaredField(\"age\")获取私有属性age");
            System.out.println("属性的类型为:"+declaredFiled.getType()+"\t属性的名称为:"+declaredFiled.getName());
            declaredFiled.setAccessible(true);//为了可以访问私有成员变量,我们需要强制设置访问权限。
            declaredFiled.set(o, 18);
            System.out.println(declaredFiled.get(o));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }
}

5 获取Method

package org.example.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectTest04 {

    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException {
        Class<User> userClass = User.class;
        Object o = userClass.newInstance();
      
        //测试getMethods()函数
        Method[] methods = userClass.getMethods();
        System.out.println("\n通过getMethods()获取所有公开方法");
        for (Method method : methods) {
            System.out.println(method.getName());
            Class<?>[] paramList = method.getParameterTypes();
            System.out.println("参数数量为:" + paramList.length);
            for (Class<?> p : paramList) {
                System.out.println("参数类型为:" + p.getTypeName());
            }
        }

        //测试getDeclaredMethods()函数
        Method[] declaredMethods = userClass.getDeclaredMethods();
        System.out.println("\n通过getdeclaredMethods()获取所有方法(包括私有,不包括继承)");
        for (Method method : declaredMethods) {
            System.out.println(method.getName());
            Class<?>[] paramList = method.getParameterTypes();
            System.out.println("参数数量为:" + paramList.length);
            for (Class<?> p : paramList) {
                System.out.println("参数类型为:" + p.getTypeName());
            }
        }

        //测试getMethod(参数)函数
        Method method = userClass.getMethod("testPublic", String.class, int.class);
        System.out.println("\n通过getMethod获取testPublic");
        System.out.println(method.getName());
        try {
            method.invoke(o, "Alice", 18);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        Class<?>[] paramList = method.getParameterTypes();
        System.out.println("参数数量为:" + paramList.length);
        for (Class<?> p : paramList) {
            System.out.println("参数类型为:" + p.getTypeName());
        }

        //测试getDeclaredMethod(参数)函数
        Method declaredMethod = userClass.getDeclaredMethod("testPrivate", String.class, int.class);
        System.out.println("\n通过getDeclaredMethod获取testPrivate方法");
        System.out.println(declaredMethod.getName());
        try {
            declaredMethod.setAccessible(true);
            declaredMethod.invoke(o, "Bob", 20);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        Class<?>[] pls = declaredMethod.getParameterTypes();
        System.out.println("参数数量为:" + pls.length);
        for (Class<?> p : pls) {
            System.out.println("参数类型为:" + p.getTypeName());
        }
    }
}

6 例子

例一

Runtime.getRuntime().exec("calc.exe");

Class.forName("java.lang.Runtime")
                .getMethod("exec", String.class)
                .invoke(
                        Class.forName("java.lang.Runtime")
                                .getMethod("getRuntime")
                                .invoke(Class.forName("java.lang.Runtime"))//此处在获取类
                        ,
                        "calc.exe"
                );

public Object invoke(Object obj, Object... args)

它的第一个参数是执行method的对象:

  • 如果这个方法是一个普通方法,那么第一个参数是类对象
  • 如果这个方法是一个静态方法,那么第一个参数是类

例二

List<String> paramList = new ArrayList<>();
paramList.add("calc.exe");
ProcessBuilder pb = new ProcessBuilder(paramList);
pb.start();

ProcessBuilder有两个构造函数

  • public ProcessBuilder(List<String> command)
  • public ProcessBuilder(String... command)

根据这两个构造函数,有两个反序列化的构造

Class.forName("java.lang.ProcessBuilder")
                .getMethod("start")
                .invoke(
                        Class.forName("java.lang.ProcessBuilder")
                                .getConstructor(List.class)
                                .newInstance(Arrays.asList("calc.exe"))
                );
((ProcessBuilder)Class.forName("java.lang.ProcessBuilder")
                .getConstructor(String[].class)
                .newInstance(new String[][]{{"calc.exe"}}))
                .start();

newInstance函数接受参数是一个Object..​也就是Object数组,它会给String[][]去掉一层。剩下的String[]匹配ProcessBuilder变量格式。

标签:反射,Java,String,System,public,println,Class,out
From: https://www.cnblogs.com/lantern-lab/p/18453598/java-reflection-1ypwc3

相关文章

  • java 按行读取文件,并筛选包含指定字符行数据
    `importjava.io.BufferedReader;importjava.io.FileNotFoundException;importjava.io.FileReader;importjava.util.Collections;importjava.util.List;importjava.util.stream.Collectors;publicclassTestController{publicstaticvoidmain(String[]......
  • Java反序列化
    Java反序列化什么是序列化和反序列化如果我们需要持久化Java对象比如将Java对象保存在文件中,或者在网络传输Java对象,这些场景都需要用到序列化。序列化:将数据结构或对象转换成二进制字节流的过程反序列化:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的......
  • 【毕设项目推荐】Java的房屋租赁系统
    今天给大家介绍一款基于Java的房屋租赁系统,页面非常精美功能且丰富项目介绍房屋租赁系统(verio_house)是一个基于SSM开发的标准JavaWeb项目。整体页面非常的简约大气(个人觉得我设计的页面还是非常的Beautiful)。整体项目的完整度较高,但是当时没有花精力去对接支付系......
  • java复制查询数组-cnblog
    java数组复制数组copyOf(待复制数组,复制后新数组的长度)如果复制后数组的长度,长于原来数组,多出来的元素会被补0,如果新数组元素少会从第一个元素,取到指定元素长度packagenb;importjava.util.Arrays;publicclasscopyOf_{publicstaticvoidmain(String[]......
  • JAVA基础: synchronized 和 lock的区别、synchronized锁机制与升级
    1synchronized和lock的区别synchronized是一个关键字,lock是一个接口,实际使用的是实现类synchronized通过触发的是系统级别的锁机制,lock是API级别的锁机制synchronized自动获得锁,自动释放锁。lock需要通过方法获得锁并释放锁synchronized可以修饰代码段和方法,lock......
  • JAVA基础:Lock不同的锁形式
    1.1可重入锁synchronized就是一个可重入锁使用lock时,常用的ReentryLock就是可重入锁当一个线程在获得a对象锁之后,可以继续重复获得对象锁代码形式就是线程调用同步代码段,在没有执行完毕前,又调用了该对象的另一个同步代码段publicclassTest4{publicstatic......
  • 【java 使用 ffmpeg 将rtsp转hls】
    java海康接口ffmpeg提示海康相关文件开发准备工具使用获取监控列表ffmpeg转换视频流视频流转换导入提示java使用SpringBoot框架jdk使用1.8版本海康通过访问OpenAPI文档中心的方式可以验证API网关是否安装成功,访问地址http://IP:Port/artemis-portal/......
  • javascript学习——CSS 操作总结
    CSS操作CSS与JavaScript是两个有着明确分工的领域,前者负责页面的视觉效果,后者负责与用户的行为互动。但是,它们毕竟同属网页开发的前端,因此不可避免有着交叉和互相配合。本章介绍如何通过JavaScript操作CSS。HTML元素的style属性操作CSS样式最简单的方法,就是......
  • javascript学习——DOM 概述
    DOM概述DOMDOM是JavaScript操作网页的接口,全称为“文档对象模型”(DocumentObjectModel)。它的作用是将网页转为一个JavaScript对象,从而可以用脚本进行各种操作(比如增删内容)。浏览器会根据DOM模型,将结构化文档(比如HTML和XML)解析成一系列的节点,再由这些节点组......
  • Java开发之JDK下载
    JDK是什么?JDK(JavaDevelopmentKit)是Java开发工具包,包含了编译、运行Java程序所需的工具和环境。如何下载JDK?访问Oracle官网:打开Oracle的Java官网:JavaDownloads|Oracle选择适合的版本:根据你的操作系统(Windows、macOS、Linux)和项目需求选择合适的JDK版本。一般来说,选......