全文内容

1: 获取字节码文件对象的三种方式
2: 获取公有,私有方法,并调用构造方法,成员方法
3: 获取并调用私有成员变量
4: 如何为实例对象的成员变量赋值
5: 文末有一些注意

tea1类代码

class tea1{
private String i;
public int j;
public tea1(){}
public tea1(int j){
this.j = j;
}
private tea1(String i,int j){
this.j = j;
this.i = i;
} @Override
public String toString() {
return "tea1{" +
"i='" + i + '\'' +
", j=" + j +
'}';
}
private void q(){
System.out.println("调用私有成员方法");
}
}

测试类代码

package 学习.反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class a {
public static void main(String[] args) throws
ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException,
InstantiationException, NoSuchFieldException {
//获取字节码文件对象的三种方式
//一(推荐):foeName()里面是类所在的全路径
//idea可以右键所在类,然后点击copy,然后点击copy reference,行了
Class<?> tea1 = Class.forName("学习.反射.tea1");
//二:通过类对象获取字节码文件对象
tea1 tea11 = new tea1();
Class<?> aClass = tea11.getClass();
//三:通过类名获取字节码文件对象
Class<?> aClass1 = tea1.getClass();
/*
提前补充:
tea1.getConstructor(),这里面的参数是字节码文件对象
举例
Constructor<?> constructor1 = tea1.getConstructor(int.class);
这句意思是:返回了tea1类中的带有一个int参数的构造器,这个构造方法
默认是公有的,私有下面会讲.
举例:Constructor<?> constructor2
=tea1.getConstructor(int.class,String.class);
意思是获取带有两个参数的构造器int与String.
相信大家可以触类旁通
*/
//获取无参构造器
Constructor<?> constructor = tea1.getConstructor();
//获取有参构造器
Constructor<?> constructor1 = tea1.getConstructor(int.class);
/*
在不使用反射机制时,私有的构造方法是在外部无法调用的,拓展一下:比
如饿汉式,懒汉式设计模式,这两种设计模式就是将构造方法私有化了,
可以自己去了解以下,也可以等我更新文章。
Constructor<?> declaredConstructor =
tea1.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
第一句是获取了一个私有的构造器对象,不过这个对象有锁
第二句就是破除锁。
*/
//获取私有构造器
Constructor<?> declaredConstructor =
tea1.getDeclaredConstructor(String.class, int.class);
//破除私有
/*
* 可以理解为公有方法在第一步找到对象就可以直接使用,而私有需要打开
* 私有锁,
* setAccessible就是打开锁
* */
declaredConstructor.setAccessible(true);
/*
可以在创建对象的时候传递参数,这个参数数量与类型要与
上边的tea1.getConstructor(int.class)相照应,否则有些运行时会出错
在这是使用上边获得的构造器来创建对象的过程
为了方便大家查看,我把上边代码贴过来了,可以一一对照
*/
//创建对象
//无参
//Constructor<?> constructor = tea1.getConstructor();
Object o = constructor.newInstance();
//有参
// Constructor<?> constructor1 = tea1.getConstructor(int.class);
Object o1 = constructor1.newInstance(1);
/*Constructor<?> declaredConstructor =
tea1.getDeclaredConstructor(String.class, int.class); */
Object a = declaredConstructor.newInstance("a", 1);
//获取方法
//这是获取公有方法,tea1.getMethod("toString")其中toString是类中 的方法名
Method toString = tea1.getMethod("toString");
//这是获取私有方法
Method declaredMethod = tea1.getDeclaredMethod("q");
//破除私有,
declaredMethod.setAccessible(true);
//下面是调用方法
//结构式:方法对象.invoke(实例对象)
//反射,反着写(狗头)
declaredMethod.invoke(o);
//输出3个结果
//使用反射机制调用方法
System.out.println(toString.invoke(o));
//直接输出就是默认调用toString
System.out.println(o1);
System.out.println(toString.invoke(a));
//获取成员变量
//获取公有变量
Field j = tea1.getField("j");
//输出a实例对象的j成员变量
System.out.println(j.get(a));
//私有成员变量
Field i = tea1.getDeclaredField("i");
//破除私有
i.setAccessible(true);
//输出a实例对象的成员变量
//结构:变量对象名.get(实例对象名)
//反射,反着写(狗头)
System.out.println(i.get(a));
//至此,获取构造方法的内容结束
//获取成员变量 //现在,获取实例对象,方法,变量都讲完了
//讲解如何为实例对象的成员变量进行赋值
//不知道大家现在能否看懂
//获取私有成员变量
Field j1 = tea1.getDeclaredField("j");
//破除私有变量
j1.setAccessible(true);
//为成员变量赋值
//j1是成员变量的实例化对象
//o是上文创建的一个对象,我把代码粘贴过来了
//Constructor<?> constructor = tea1.getConstructor();
//Object o = constructor.newInstance();
//结构:成员变量的实例化对象.set(类的实例化对象,对应的成员变量的值)
//400是int,原因是:
//Field j1 = tea1.getDeclaredField("j");
//而j在类中是int类型,一定要类型对应
j1.set(o,400);
//获取并输出o对象的成员变量j的值
System.out.println(j1.get(o));
}
}

注意:可以按照获得私有构造器,私有方法,私有对象的函数处理公有方法,这样不会在一些未知的情况下出错。
推荐大家都使用Class.forName()来获取字节码文件对象。
谢谢大家。

最新文章

  1. Fragment的生命周期
  2. Good Bye 2016 - B
  3. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)D Dense Subsequence
  4. (转)C语言union(联合体 共用体)
  5. phaser源码解析(三) Phaser.Utils类下isPlainObject方法
  6. unity3d shader之God Ray上帝之光
  7. web开发技术中Servlet技术的概述
  8. python爬虫爬取人人车(二手车)、利用padas、matplotlib生成图表,将信息打成csv格式
  9. .net core 2.x - 日志 - to elasiticsearch
  10. linux中的wc命令
  11. etcd 增减节点
  12. 清理sql2012数据库日志
  13. Hangfire Net Core2
  14. 9.8 翻译系列:数据注解特性之--Required 【EF 6 Code-First系列】
  15. [LeetCode] 876. Middle of the Linked List_Easy tag: Linked List ** slow, fast pointers
  16. AWS 相关阅读
  17. jquery获取浏览器类型和版本号的方法
  18. node.js---sails项目开发(4)---配置MongoDB数据库连接
  19. 洛谷 4106 / bzoj 3614 [HEOI2014]逻辑翻译——思路+类似FWT
  20. kubeadm常见报错和解决方法

热门文章

  1. static关键字——JavaSE基础
  2. SpringBoot之:SpringBoot中使用HATEOAS
  3. 【RocketMQ】MQ消息发送
  4. JS:对象调方法1
  5. BUUCTF-刷新过的图片
  6. Pyinstaller打包pikepdf失败的问题排查
  7. MySQL通过binlog日志恢复数据
  8. 『现学现忘』Git后悔药 — 31、reset版本回退命令总结
  9. CMU15445 (Fall 2019) 之 Project#4 - Logging &amp; Recovery 详解
  10. 4-5 Spring Boot