Java反射原理分析
一:Java的反射就是把Java类中的各种成分映射成相应的Java类。
例如:一个Java类中用一个Class类的对象来表示此Java类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个的Java类来表示。
比如汽车是一个类,汽车中的发动机中的发动机,变速箱等一个一个个的类。
二:一句话概括:反射就是把Java类中的各个成分映射成相应的Java类。
三:反射的基石:Class类(Java程序中的各个Java类属于同一事物,描述这类事务的类就是Class类)
四:表示Java类的Class类显然要提供一系列的方法来获取其中的变量,方法,构造方法,修饰符,包等信息(对应映射类Field,Method,Constructor,Package等)
五:得到映射对象必须先得到字节码!三种方式获取字节码!
1. 对象.getClass() Person p=new Person(); Class clazz=p.getClass(); //类的字节码已经加载到内存,只需要对象调用
2. 类加载器 Class clazz=Class.forName("java.lang.String"); //类的完整名称
3. 类名.Class Class clazz=Person.class;
六:8个基本类型对应8个Class对象(boolean, byte, char, short, int, long, float, double)+void
七:映射类
Constructor类:代表某个类中的一个构造方法
1.得到某个类中的所有构造方法:
Constructor constructors[]=Class.forName("java.lang.String").getConstructors();
2.得到其中一个构造方法:
Constructor constructor=Class.forName("java.lang.String").getConstructor("StringBuffer.Class"); //后面跟参数的字节码
3.创建实例对象:
通常方式:String str1=new String(new StringBuffer("abc"));
反射方式:String str2=(String)constuctor.newInstance(new BufferString("abc")); //通过构造方法再映射的对象,参数的类型必须一致
PS:得到构造方法Constructor的对象时必须传递参数类型,创建实例化对象时必须是相同的参数类型!!
Class -> Constructor -> new object
Class.newInstance()方法:
String str=(String)Class.forName("java.lang.String").newInstance(); //该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象用到了缓存机制来保存默认构造方法的实例对象。
Field类:代表Java类中的成员变量
Method类:代表Java类中成员方法的反射
String str=new String("abc");
Method m=String.class.getMethod("charAt",int.class);
System.out.println(m.invoke(str,1);
通过反射方式得到字符码的某个方法m,再拿着此方法作用于某个对象str,只用对象自己拿着方法调用执行。m只相当于介质,执行的还是str对象。
PS:调用方法必须在某个对象上调,参数类型必须一致。当对象为null时,执行的是静态方法。
八:Java测试代码
/*
* 测试反射的Field(Java类的成员变量)类
*/
public class ReflectTest2 {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "boll";
public String str3 = "call";
public ReflectTest2(int x, int y) {
super();
this.x = x;
this.y = y;
}
public static void main(String[] args) {
}
@Override
public String toString() {
return "ReflectTest2 [x=" + x + ", y=" + y + ", str1=" + str1
+ ", str2=" + str2 + ", str3=" + str3 + "]";
}
}
/*
* 映射类
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
String str = "abc";
// ----------------字节码----------------------------------
// 得到字节码的3种方式
Class cls1 = str.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
// PS:cls1,cls2,cls3都是同一份字节码对象.cls1=cls2=cls3
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
System.out.println(cls1.isPrimitive()); // 返回false. String不是基本类型字节码。
System.out.println(int.class == Integer.class); // 返回false
System.out.println(int.class == Integer.TYPE); // 返回true
// .TYPE返回其包装类型的字节码
System.out.println(int[].class.isPrimitive()); // 返回false判断是否是基本数据类型的映射
System.out.println(int[].class.isArray()); // 返回true 判断字节码类型是数组类型
// -------------------------Constructor--------------------------------
// 得到某一个构造方法: 参数类型为StringBuffer类型
Constructor constructor = String.class.getConstructor(StringBuffer.class);
// 通过构造方法创建实例化对象
// 通常方式
String str1 = new String(new StringBuffer("abc"));
// 反射方式
String str2 = (String) constructor.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));
// PS:得到构造方法constructor对象时必须传递参数类型,创建实例化对象时必须是相同的参数类型
// -----------------------Filed------------------------------------------
ReflectTest2 rt = new ReflectTest2(2, 3);
// 得到Java类中的成员变量
Field fieldY = rt.getClass().getField("y");
// fieldY不是Java对象身上的变量,而是类上,从某个Java对象中取出具体的值
System.out.println(fieldY.get(rt));
// 对于私有不可见变量
Field fieldX = rt.getClass().getDeclaredField("x");
fieldX.setAccessible(true); // 暴力反射
System.out.println(fieldX.get(rt));
changeValue(rt);
System.out.println(rt);
// --------------------------Method-----------------------------------------
// 通过反射得到Java类方法
Method methodCharAt = String.class.getMethod("charAt", int.class);
// 调用方法必须在某个对象上调
System.out.println(methodCharAt.invoke(str1, 1));
// 反射执行类中的main方法 main方法为静态方法。传递对象可为null
Method methodMain = Class.forName("com.test.MethodTest").getMethod(
"main", String[].class);
System.out.println(methodMain.invoke(null, new Object[] { new String[] {
"aaa", "bbb" } }));
// ---------------------------数组映射-----------------------------------------
printObject(new String[] { "aaa", "bbb" });
}
// 打印数组
private static void printObject(Object obj) {
Class clazz = obj.getClass();
if (clazz.isArray()) {
int length = Array.getLength(obj);
for (int i = 0; i < length; i++) {
System.out.println(Array.get(obj, i));
}
} else {
System.out.println(obj);
}
}
// field运用:改变类型名为String类型的成员变量的值
private static void changeValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
// 比较字节码用"="比较 因为是同一份字节码
if (field.getType() == String.class) {
String oldValue = (String) field.get(obj);
String newValue = oldValue.replace("b", "a");
// 重新设值
field.set(obj, newValue);
}
}
}
}
// method运用。调用类中的main方法
class MethodTest {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
Java反射原理分析相关推荐
- Java反射原理及应用
Java反射原理及应用 概述 底层原理 类加载 反射.直接调用的区别 反射调用性能 反射慢本质 反射应用场景 应用示例 概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...
- java dump分析工具_java性能分析与常用工具
本次源码已放在Github:https://github.com/nateshao/jvm-tuning 个人博客 https://nateshao.gitee.io http://www.nates ...
- 【Java 虚拟机原理】垃圾回收算法( Java VisualVM 工具 | 安装 Visual GC 插件 | 使用 Java VisualVM 分析 GC 内存 )
文章目录 一.Java VisualVM 工具安装 Visual GC 插件 二.使用 Java VisualVM 分析 GC 内存 一.Java VisualVM 工具安装 Visual GC 插件 ...
- linux java性能监控工具_性能监控工具以及java堆分析OOM
一.性能监控工具 1.系统性能监控 Linux -确定系统运行的整体状态,基本定位问题所在 -uptime: ------系统时间 ------运行时间(例子中为127天) ------连接数(每个终 ...
- java异常——分析堆栈跟踪元素+使用异常机制的技巧
[0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常--分析堆栈跟踪元素+使用异常机制的技巧 的相关知识: [1]分析堆栈跟踪元素相关 ...
- 开源java性能分析工具_Java性能监控:您应该知道的5个开源工具
开源java性能分析工具 鲜为人知但有用:开源应用程序性能监视的状态 对于任何应用程序来说,最重要的事情之一就是性能. 我们要确保用户获得他们能获得的最佳体验,并想知道我们的应用已启动并正在运行. 这 ...
- java编译器分析_Java反编译器的剖析
java编译器分析 简单地说,反编译器尝试将源代码转换为目标代码. 但是有很多有趣的复杂性-Java源代码是结构化的: 字节码当然不是. 而且,转换不是一对一的:两个不同的Java程序可能会产生相同的 ...
- java超出gc开销限制_超出了GC开销限制– Java堆分析
java超出gc开销限制 这篇文章是我们原来的GC开销超出问题模式的延续. 正确的Java堆分析对于消除OutOfMemoryError:GC开销问题至关重要. 如果您不熟悉此Java HotSp ...
- 超出了GC开销限制– Java堆分析
这篇文章是我们原来的GC超出限制的问题模式帖子的延续. 正确的Java堆分析对于消除OutOfMemoryError:GC开销问题至关重要. 如果您不熟悉此Java HotSpot 1.6错误,建 ...
最新文章
- Xmanager连接Linux 9的方法
- 关于在VS2010中学习c++的MFC
- mac上使用zsh配置环境变量
- TCP的三个接收队列
- Elasticsearch大文件搜索
- kali装电脑_Kali Linux可以安装到平板电脑吗?
- python爬电影_使用Python多线程爬虫爬取电影天堂资源
- 花生采摘(洛谷-P1086)
- c语言的point函数,C语言中friend友元函数详细解析
- oppo手机维语字体_老年人上网困难重重?学会OPPO这几个功能无后顾之忧
- Qtcreator中经常使用快捷键总结
- python利用微信的方法_作为程序员,如何利用Python玩转微信,让你的微信与众不同...
- 收购小蓝单车部分资产、与ofo蜜月期结束,滴滴重构共享单车布局
- MySQL服务无法正常启动的解决方法(1053错误)
- 《java编程思想》读书笔记(二)第五章(2)
- 常见网络问题——架设篇
- 简述具有五层协议的网络体系结构各层的主要功能。
- 腾讯2021校园招聘-后台综合-第一次笔试 8.23 20.00-22.00 Apare_xzc
- 简明现代魔法 php,PHP生成强密码
- vue 项目实践 -ele 表单验证
热门文章
- JavaEE企业级应用开发第18章 BOOT客户管理系统的分享
- 20个首页流行布局样式,你喜欢哪个?
- android 检测广告代码,Admob测试广告未在Android应用程序中显示(示例代码)
- java计算机毕业设计剧院售票系统MyBatis+系统+LW文档+源码+调试部署
- 在Unity中构建Pong克隆:UI和游戏玩法
- Sqlcmd使用详解
- linux kernel tcp拥塞处理之cubic算法
- deepin系统入坑记录
- sudo apt install nvidia 后无法进入登录界面 /Ubuntu无法进入登录界面 亲测有效!
- 微信小程序getPhoneNumber接口code=40013