reflection反射
reflection反射
动态和静态语言
动态语言
动态语言就是一类在运行时可以改变其结构的语言,通俗点说就是在运行时代码可以根据某些条件改变自身结构
主要动态语言:object-C,C#,JavaScript,PHP,Python等.
静态语言
- 与动态语言相对应,运行时结构不可变的语言就是静态语言。如java,c,c++。
- java不是动态语言,但java可以被称为“准动态语言”。即java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性,java动态性让编程时更加灵活
java反射机制概述
反射概述
- 反射是java被视为动态语言的关键
- 反射机制允许程序在运行期间借助于Reflection API取得任何类的内部信息,
- 反射能直接操作任意对象的内部属性以及方法
- 反射就是我们正常的方式反过来
- 反射可以通过对象反射出类的名称
- 一个类被加载后,类的整个结构都会被封装在Class对象中
狂神 反射 反射概述视频06:29
在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息,这个对象就想一面镜子,透过这面镜子看到类的结构,所以我们称之为:反射
狂神 反射 获得反射对象01:29
反射的优缺点
优点
- 可以实现动态创建对象和编译,体现出很大的灵活性
缺点
- 对性能有影响。使用反射基本上是一解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于直接相同操作。
Class类
Class的概述
狂神 反射 得到Class类的几种方式00:04
Class的常用方法
狂神 反射 得到Class类的几种方式01:47
哪些类型有Class对象
狂神 反射 所有类型的Class对象
![哪些类型有Class对象](C:\Users\lyj\Desktop\Learning summary\img\reflection反射\哪些类型有Class对象.png)
Class c1 = Object.class;//类
Class c2 = Comparable.class;//接口
Class c3=String[].class;//一维数组
Class c4=int[][].class;//二维数组
Class c5= Override.class;//注解
Class c6= ElementType.class;//枚举
Class c7=Integer.class;//基本类型
Class c8=void.class;//空
Class c9=Class.class;//Class
java内存分析
狂神类加载内存分析00:23
类的加载过程
狂神类加载内存分析00:39
类的加载和Class Loader的理解
加载
- 编译过后将class文件加载到内存当中,并且将这些静态数据转换成方法区的运行时数据结构,然后生成一个Class对象
链接
- 将java类的二进制代码合并到JVM的运行环境中
验证
- 确保加载的类信息符合JVM规范,没有安全方面的问题
准备
- 正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配
解析
- 虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
初始化
- 执行类构造器()方法的过程。类构造器()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造器信息的,不是构造该类对象的构造器)。
- 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
- 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步。
public class Test04 {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
}
}
class A{
static {
System.out.println("A类静态代码块初始化");
m=300;
}
static int m = 100;
public A() {
System.out.println("A类的无参构造初始化");
}
}
什么时候会发生类初始化
类主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化main方法所在的类
- new一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
- 当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类
类的被动引用(不会发生类的初始化)
- 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态常量,不会导致子类初始化
- 通过数组定义类引用,不会触发此类的初始化
- 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)
类加载器的作用
类加载的作用
- 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
类缓存
- 标准的javaSE类加载器可以按照要求查找类,但一旦某个类被加载到加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。
JVM规范定义了如下类型的加载器
反射的方法
获取类名
System.out.println(c1.getName());//获得包名加类名(由于我直接在src下写的类所有没有包名)
System.out.println(c1.getSimpleName());//获得类名
获取属性
user类内全部属性都为private
//获得类的属性
System.out.println("==============");
Field[] fields = c1.getFields();//只能找到public属性
for (Field field : fields) {
System.out.println(field);
}
Field[] declaredFields = c1.getDeclaredFields();//找到全部的属性
for (Field field : declaredFields) {
System.out.println(field);
}
System.out.println("==================");
System.out.println(c1.getDeclaredField("name"));//获取指定属性不管修饰符是什么
System.out.println(c1.getField("name"));//只能指定获取public属性
因为name是private所有报异常
获得类的全部类
//获取全部类的方法
System.out.println("==================");
Method[] methods = c1.getMethods();//获得本类和父类全部的public方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==================");
methods=c1.getDeclaredMethods();//获得本类的所有方法(包括private)
for (Method method : methods) {
System.out.println(method);
}
- 获得本类和父类全部的public方法
- 获得本类的所有方法(包括private)
获得指定类的方法
//获得类的指定方法
//为什么后面要参数,因为java里有重载
System.out.println("==================");
Method getName = c1.getMethod("getName",null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(setName);
System.out.println(getName);
获得构造器
//获得构造器
System.out.println("==================");
Constructor[] constructors = c1.getConstructors();//获得public构造器
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("==================");
constructors = c1.getDeclaredConstructors();//获取全部构造器(后面单列模式构造方法是private)
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
获得指定构造器
//获得指定构造器
System.out.println("==================");
Constructor constructor = c1.getConstructor(String.class, int.class, int.class);//获得public构造器
System.out.println(constructor);
constructor=c1.getDeclaredConstructor(String.class, int.class, int.class);//获取构造器(后面单列模式构造方法是private)
System.out.println(constructor);
有了Class对象,能做什么?
public static void main(String[] args) throws Exception {
//获得CLass对象
Class c1 = Class.forName("User");
//构造一个对象
User user = (User) c1.newInstance();
System.out.println(user);
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) constructor.newInstance("青牛", 1, 18);
System.out.println(user2);*/
//通过反射调用普通方法
User user = (User) c1.newInstance();
//通过反射调用方法
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user,"青牛");
System.out.println(user.getName());
//通过反射操作属性
User user = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,我们需要关闭程序的安全检测
name.setAccessible(true);//这个就是关闭检测的,参数写true
name.set(user,"青牛");
System.out.println(user.getName());
}
setAccessible
性能测试
//普通方式调用
public static void test01(){
User user =new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 2000000000; i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方式执行时间:"+(endTime-startTime)+"ms");
}
//通过反射调用
public static void test02() throws Exception {
User user =new User();
Class c1 = user.getClass();
Method getName = c1.getMethod("getName", null);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 2000000000; i++) {
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式执行时间:"+(endTime-startTime)+"ms");
}
//通过反射调用 关闭检测
public static void test03() throws Exception {
User user =new User();
Class c1 = user.getClass();
Method getName = c1.getMethod("getName", null);
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 2000000000; i++) {
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射关闭检测方式执行时间:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws Exception {
test01();
test02();
test03();
}
- 结果
reflection反射的更多相关文章
- 代替Reflection(反射)的一些方法
Reflection(反射)是深入学习.Net必须掌握的技能之一.最初学Reflection的时候,的确是被惊住了,原来还可以这样.只要给你一个Assembly, 你就能获取到其中所有的类型,根据类型 ...
- 代替Reflection(反射)的一些方法(转)
作者:JustRun 林肯: http://www.cnblogs.com/JustRun1983/p/3830764.html 代替Reflection(反射)的一些方法(转) 2014-07-08 ...
- Java进阶之reflection(反射机制)——反射概念与基础
反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...
- Java Reflection 反射基础
反射基础: package reflection; /** * Created by : Infaraway * DATE : 2017/3/2 * Time : 23:06 * Funtion : ...
- List GroupBy真实用法,Reflection(反射)用法,Enum用法,正则,搜索下拉布局
1.List GroupBy 用法 var _roomProducts = homesingProducts.GroupBy(t => t.RoomName); RoomedProducts ...
- java学习--Reflection反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- PHP的Reflection反射机制
更多内容推荐微信公众号,欢迎关注: 原文地址: http://www.nowamagic.net/php/php_Reflection.php PHP5添加了一项新的功能:Reflection.这个功 ...
- C# 反射Reflection——反射反射程序员的快乐
一.什么是反射 反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata. 反射是无处不在的,MVC-Asp.Ne ...
- Java之reflection(反射机制)——通过反射操作泛型,注解
一.反射操作泛型(Generic) Java采用泛型擦除机制来引入泛型.Java中的泛型仅仅是给编译器Javac使用的,确保数据的安全性和免去强制类型转换的麻烦.但是编译一旦完成,所有和泛型有关的类型 ...
- C# Reflection反射机制
一.反射 什么是反射 .Net的应用程序由几个部分:'程序集(Assembly)'.'模块(Module)'.'类型(class)'组成: 反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组 ...
随机推荐
- Java基础__06.注解和反射
注解 什么是注解? 1.注解:annocation,是从JDK5.0开始引进入的新技术. 2.注解的作用: 不是程序本身,可以对程序做出解释,这一点和注释一样: 可以被其他程序读取,这点是和注释的区别 ...
- window操作
1.进入目录 cd ... 2. 进入D盘 D: 3.读取文件内容 type file
- jdk 13 添加 jre
问题: 安装 jdk 13 版本后发现没有 jre . 解决方法: 1.进入 jdk 安装目录(如:D:\Program\Java\jdk-13.0.2\) 2.在 jdk 安装目录打开命令行,输入以 ...
- ToLua中判断引用的C#对象是否为nil
C#层对象已经删除了,但是lua层判断不为nil.然后lua调用了,又会报nil的错误. 这里提供了一种判断方式. lua里的判断.这个Util.IsNull()是C#层代码. function He ...
- 特别好用的题库(oj)
tk.hustoj.com 每次做题时,我都会对"外部导入"这四个字感到迷惑: 这些题,究竟是从哪里"导入"的? 我们不为而知...... 直到后来...... ...
- ubuntu 逻辑卷增加磁盘
使用lv* 相关的命令 lvdisplay lvscan ACTIVE '/dev/ubuntu-vg/ubuntu-lv' [<74.00 GiB] inherit lv ...
- 如何把百度地图左边的搜索列表导出成excel里?
有很多人问我,怎么样能够快速的把BAIDU地图左边的搜索列表里的商家地图,电话,导出到EXCEL里. 我就开发了一个小软件,专门为快速的实现导出数据到EXCEL. 为了使用方便,已经将全国的所又省份, ...
- C# 笔记--Sendkeys winform窗体控件回车及全选
SendKeys.Send() 向活动应用程序发送击键 SendKeys.SendWait() 向活动应用程序发送给定的键,然后等待消息被处理 这两个方法可以发送组合键,需要注意的是字母按键应为小写. ...
- git 指令:丢弃本地所有未提交的更改
git clean -df //丢弃所有 untracked 的文件 git reset --hard //将 tracked 的文件重置到前一个版本
- 【ZYNQ学习】各个主题的值得看的博客
在学习ZYNQ时会遇到不少问题,这时我们一方面要在DocNav找Xilinx的官方文档,另一方面要参考别人的一些记录的解决好的办法,我在学习的时候看到了不少大佬的博客,给我带来了很大帮助.在这篇博客, ...