暴力反射---如何给私有的字段赋值以及调用私有的方法

暴力反射---如何给私有的字段赋值以及调用私有的方法

一、简单了解下什么是反射

1.1、反射:在程序运行过程中(动态),可以对任意一个类型进行任意的操作。例如:加载任意类型、调用类型的任意方法、获取任意的成员变量、构造方法,可以创建该类型的对象

1.2、对于任意一个对象,都能调用这个对象的任意一个方法

1.​3、如果要获取一个类型的各种内容,首先要获取这个类的字节码对象(字节码对象属于 Class类型)

1.​4、解剖这个类型,获取类中的成员,需要使用Class类型中定义的方法

1.​5、这种动态获取信息以及动态访问成员的方式,称为:反射

很多学习java的人或许有点疑惑 “反射到底有什么用?” 因为没有反射的话,对一个类的任意操作都需要重新关闭启动程序,简单点就是没有反射的程序都是“静态”的,有了反射,程序就转变成了“动态”其实就是上面说的在程序运行过程中能够对任意类进行操作

简单反射例子:

public static void main(String[] args) throws Exception {
		//获取字节码对象(Class对象)
        Class<Cat> catClass = Cat.class;
        //调用newInstance()方法获取对象
        Cat cat = catClass.newInstance();
    }

二、暴力反射

  • 常用方法:
  • newInstance():创建这个字节码描述的类型的实例对象
  • getDeclaredXxx方法:可以获取类中的所有声明的成员(属性、方法、内部类),私有的成员也可以获取到
  • setAccessible(boolean flag):设定当前对象是否可以访问

建一个person类

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

    private void show(String name ,int age){
        System.out.println("我叫"+name+"\t"+"今年"+age+"岁了");
    }

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

暴力反射代码案例:

public class PersonReflection {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //获取字节码对象(Class对象)
        Class<Person> personClass = Person.class;
        //获取私有字段(属性)
        Field name = personClass.getDeclaredField("name");
        Field age = personClass.getDeclaredField("age");
        //设置允许访问
        name.setAccessible(true);
        age.setAccessible(true);

        //先通过反射获取对象,为下面字段赋值和方法执行服务
        Person person = personClass.newInstance();

        //给字段(属性)设置值
        name.set(person,"lichaohua");
        age.set(person,21);

        //获取私有方法
        Method show = personClass.getDeclaredMethod("show", String.class, int.class);
        //设置允许访问
        show.setAccessible(true);
        //调用方法
        show.invoke(person,person.getName(),person.getAge());

    } }

输出结果:

在这里插入图片描述

  • 38
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 27
    评论
CruiseYoung提供的带有详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 该资料是《Visual C++ 2005入门经典》的源代码及课后练习答案 对应的书籍资料见: Visual C++ 2005入门经典 基本信息 原书名: Ivor Horton's Beginning Visual C++ 2005 原出版社: Wiley 作者: (美)Ivor Horton 译者: 李颂华 康会光 出版社:清华大学出版社 ISBN:9787302142713 上架时间:2007-2-12 出版日期:2007 年1月 开本:16开 页码:1046 版次:1-1 编辑推荐   本书由编程语言先驱者Ivor Horton倾力而著,是国内第一本全面、深入介绍Visual C++ 2005的经典之作! 内容简介   本书系编程语言先驱者Ivor Horton的经典之作,是学习C++编程最畅销的图书品种之一,不仅涵盖了Visual C++ .NET编程知识,还全面介绍了标准C++语言和.NET C++/CLI。本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2005的基础知识,并全面掌握在MFC和Windows Forms中访问数据源的技术。此外,本书各章后面的习题将有助于读者温故而知新,并尽快成为C++高效程序员。...    作译者   Ivor Horton是世界著名的计算机图书作家,主要从事与编程相关的顾问及撰写工作,曾帮助无数程序员步入编程的殿堂。他曾在IBM工作多年,能使用多种语言进行编程(在多种机器上使用汇编语言和高级语言),设计和实现了实时闭环工业控制系统。Horton拥有丰富的教学经验(教学内容包括C、C++、Fortran、PL/1、APL等),同时还是机械、加工和电子CAD系统、机械CAM系统和DNC/CNC系统方面的专家。Ivor Horton还著有Beginning Visual C++ 6、Beginning C Programming和Beginning Java 2等多部入门级好书。 目录 封面 -18 前言 -14 目录 -9 第1章 使用Visual C++ 2005编程 1 1.1 .NET Framework 1 1.2 CLR 2 1.3 编写C++应用程序 3 1.4 学习Windows编程 4 1.4.1 学习C++ 4 1.4.2 C++标准 5 1.4.3 控制台应用程序 5 1.4.4 Windows编程概念 6 1.5 集成开发环境简介 7 1.6 使用IDE 9 1.6.1 工具栏选项 9 1.6.2 可停靠的工具栏 10 1.6.3 文档 11 1.6.4 项目和解决方案 11 1.6.5 设置Visual C++ 2005的选项 23 1.6.6 创建和执行Windows应用程序 24 1.6.7 创建Windows Forms应用程序 26 1.7 小结 29 第2章 数据、变量和计算 31 2.1 C++程序结构 31 2.1.1 程序注释 36 2.1.2 #include指令——头文件 37 2.1.3 命名空间和using声明 37 2.1.4 main()函数 38 2.1.5 程序语句 38 2.1.6 空白 40 2.1.7 语句块 41 2.1.8 自动生成的控制台程序 41 2.2 定义变量 42 2.2.1 命名变量 43 2.2.2 C++中的关键字 43 2.2.3 声明变量 44 2.2.4 变量的初值 44 2.3 基本数据类型 45 2.3.1 整型变量 45 2.3.2 字符数据类型 46 2.3.3 整型修饰符 47 2.3.4 布尔类型 48 2.3.5 浮点类型 48 2.3.6 ISO/ANSI C++中的基本类型 49 2.3.7 字面值 50 2.3.8 定义数据类型的同义词 50 2.3.9 具有特定值集的变量 51 2.3.10 指定枚举常量的类型 52 2.4 基本的输入/输出操作 53 2.4.1 从键盘输入 53 2.4.2 到命令行的输出 53 2.4.3 格式化输出 54 2.4.4 转义序列 55 2.5 C++中的计算 57 2.5.1 赋值语句 57 2.5.2 算术运算 58 2.5.3 计算余数 63 2.5.4 修改变量 63 2.5.5 增量和减量运算符 64 2.5.6 计算
1. 反射: Class 类的实例表示正在运行的 Java 应用程序中的类和接口; 枚举是一种类,注解(指的是注解Annotation)是一种接口; 每个数组都是 Class字节码类中的一个具体 对象 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象; 注意 : 1、 Class类 和它的实例的产生: Class的对象是已经存在的类型, 所以不能够直接new一个Class对象出来,是通过Class类中的一个方法获取到的。 例如:通过全限定路径类名 2、同一种类型不管通过什么方式得到Class的实例都是相等的;一个类型的字节码对象只有一份,在元空间。 3、Class的实例就看成是Java中我们学过的所有的数据类型在JVM中存在的一种状态(字节码对象) String.class int.class List.class int[].class 1.概念:通过一个全限定类名,获取字节码文件 2.作用: 1. 提高开发灵活度,提高程序的扩展性 2. 框架(提高开发效率的别人封装好的代码)底层都是使用反射技术。例如:Tomcat、Spring... 3. 缺点:破坏封装性,性能低下(以后,能不用反射技术就不用) 3. 使用:(重点) 1. 获取字节码文件 1. 1.1 Class clazz = Class.forName(全限定路径名) (最多使用)默认就是调用下面的方法 1.2 static 类<?> forName(String name, boolean initialize, ClassLoader loader) name:全限定路径名 initialize:表示是否初始化,默认是false loader:可以指定一个类加载器加载字节码文件 2. 全限定类名.class 3. 对象名.getClass() Class类中方法newInstance():创建当前字节码对象(只能调用无参且是public修饰的构造方法) 2. 根据字节码文件获取构造方法、普通方法字段等 构造方法 Constructor[] constructors = clazz.getConstructors() 获取public修饰的构造方法数组 Constructor[] constructors = clazz.getDeclaredConstructors() 获取任意权限的所有造方法数组 Constructor constructor = clazz.getConstructor(Class 参数字节码)根据参数类型获取public修饰的指定的的构造方法 Constructor constructor = clazz.getDeclearConstructor(Class 参数字节码) 获取任意访问权限指定的构造方法 //通过构造方法对象去用构造方法创建对象 => 相当于new 一个对象 Object instance = constructor.newInstance(Object 实参);//可以创建任意访问权限的有参或者无参构造 普通方法 Method[] methods = clazz.getMethods() 获取public修饰的构造方法数组,有父类中的方法 Method[] methods = clazz.getDeclaredMethods() 获取任意访问权限所有造方法数组,并且都是自己的方法 Method method = clazz.getMethod(String methodName,Class... 参数字节码)根据方法名和参数类型获取指定的的方法 methodName:方法名 Class:形参类型。如果方法没有形参,则Class可变参数不用写 Method method = clazz.getDeclaredMethod(String methodName,Class... 参数字节码)根据方法名和参数类型获取指定的的方法 methodName:方法名 Class:形参类型。如果方法没有形参,则Class可变参数不用写 //通过普通方法对象调用执行方法 method.invoke(Object obj,Object... args); obj:对象。如果是对象的方法,就传入一个当前字节码创建的对象,如果是static方法,则写null args:就是具体实参 字段 Field[] fields = clazz.getFields() 获取public修饰的字段 Field[] fields = clazz.getDeclaredFields() 获取任意权限所有字段 Field field = clazz.getDeclaredField(String fieldName) 根据字段名获取任意访问权限的指定字段 Field field = clazz.Field(String fieldName)根据字段名获取public的指定字段 //通过当前的字段对象,给某一个字段赋值取值 field.get(Object obj);//如果是属于非static,就传入一个对象,如果是静态的,就传入null obj:对象 field.set(Object obj, Object value);//如果是属于非static,就传入一个对象,如果是静态的,就传入null obj:对象 value:值 String getName() 获取全限定类名(全限定,包含包名) Class类中方法 String getSimpleName() 获取类名简称 Class类中方法 Package getPackage() 获取包名 Class类中方法 T newInstance() 根据当前字节码创建对应的对象 Class类中方法 注意: 1. Class类中方法newInstance():创建当前字节码对象(只能调用无参且是public修饰的构造方法) 2. Constructor类中方法newInstance(Object 实参);//可以创建任意访问权限的有参或者无参构造 3. 私有方法字段、构造方法都必须破坏封装才能使用: public void setAccessible(boolean flag) true表示破坏封装,false是不破坏 是哪个private修饰的方法字段、构造方法需要执行,就需要用这个对象破坏哪一个的封装 例如: //获取cn.itsource.reflect.User字节码文件 Class<?> clazz = Class.forName("cn.itsource.reflect.User"); //获取User的有String参构造 Constructor<?> constructor = clazz.getConstructor(String.class); //调用有参String构造,创建一个User对象 Object newInstance = constructor.newInstance("某文"); //获取private修饰的方法:testPrivate Method method2 = clazz.getDeclaredMethod("testPrivate"); method2.setAccessible(true);//破坏普通方法Method封装 //破坏封装后就可以执行了 Object invoke2 = method2.invoke(newInstance);//没有形参就不用写 System.out.println(invoke2); 4. 调用static方法字段: 例如: Field field = clazz.getDeclaredField("country");//获取任意访问权限静态变量country field.set(null, "中国");//因为字段country是static修饰,所以不用对象调用,就传入null。字段country赋值:中文 Object object = field.get(null);//字段country取值 System.out.println(object); 2. 注解: 1.概念: 就是一个标签,有标签后,就具有某一些标签的特性。 本质就是跟类、接口、枚举平级的新结构 2.作用: 1. 帮助程序员校验代码 2. 可以提高开发效率和程序的扩展性 @Test @Before @After 3. 可以生成文档说明 api 操作步骤: 1.选中项目/代码,右键选中Export 2.输入Javadoc 3.第一个next(可以设置生成文档注释的目录),第二个next,设置字符集 如果是UTF-8编码,且有中文,请输入-encoding UTF-8 -charset UTF-8 4. 勾选一个生成完毕后,直接通过浏览器打开的选项 5. finish 3.使用:(重点) 1. 使用jdk或者别人定义好的标签 @ + 注解的名称 -- 比如@Override ->注解 2. 使用自定义的标签 1.JDK的元注解:就是专门用来声明其他注解的注解 作用:通过元注解了解其他注解的使用特点,还可以自定义注解 2.元注解: 1. @Target @Target 作用 用来限制被修饰注解的使用范围,即注解可以在类的哪些成员上使用 @Target 取值使用ElementType.() 1. CONSTRUCTOR:可以在构造器上使用注解 2. FIELD:可以在字段上使用注解 3. LOCAL_VARIABLE:可以在局部变量上使用注解 4. METHOD:可以在普通方法上使用注解 5. PACKAGE:可以在包上使用注解 6. PARAMETER:可以在参数列表上使用注解 7. TYPE:可以在类、接口(包括注解类型) 或enum上使用注解 例如:@Target(ElementType.METHOD)//意味着@Override只能在普通方法上使用 public @interface Override { } 2. @Retention

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lichaohua!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值