在学校学习Java时,由于学的不扎实,也没经历过太多实战项目,所以很多重要的知识点瞟一眼就过去了,比如现在要讲的反射,当时直接就忽略掉了,可现在发现很多地方需要反射,不得不重新学习一下,上学欠了太多债,是时候慢慢还清了。

(一)什么是反射?

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

简单的来说:

1.通过new关键字创建对象操作对象,在编译时就已经确定。

2.通过反射可以在程序运行过程中动态的操作对象,可以获得编译期无法获得的信息,动态操作最大限度发挥了java扩展性。

反射是框架的灵魂,它可以有效地降低类之间的耦合,很多框架都运用了反射原理,例如hibernate 的实体类,Spring 的 AOP等等都有反射的实现

(二)反射的具体实现

想要实现反射,就必须先拿到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息,每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象.

1. 获取字节码文件对象(Class)的三种方式

/*** 方式一:

* Object中的getClass方法来获取Class对象

* 使用这方式必须有具体的类,并创建对象。

* 这种方式使用的少,一般是传的是Object,不知道类型的时候才使用。*/Object obj=newProson();

Class clazz1=obj.getClass();

System.err.println("通过getClass():"+clazz1);/*** 方式二:

* 直接通过 类名.class来获取Class对象。

* 任何类型中都具有隐含的静态成员变量class,使用简单,但是扩展性还是不足。*/Class clazz2=Proson.class;

System.err.println("通过类名.class:"+clazz2);/*** 方式三:

* 通过Class 对象的forName()静态方法来获取Class对象。

* 使用最多,通过类的全限定名,但可能抛出ClassNotFoundException异常*/Class clazz3= Class.forName("com.xiaoli.bean.Proson");

System.err.println("通过类的全限定名:"+clazz3);//比较三种方法对象是否是相同实例。

System.err.println(clazz1==clazz2);

System.err.println(clazz1==clazz3);

System.err.println(clazz2==clazz3);

运行结果得知

三种方法都可以获取字节码文件对象。

一个类在 JVM 中只会有一个 Class 实例(比较之后全为true)

2. 创建对象的方式。

Proson类

public classProson {//私有属性

privateString name;//公有属性

publicInteger age;//无参构造

publicProson() {

}//有参构造

publicProson(String name, Integer age) {this.name =name;this.age =age;

}//私有方法

private voidmethod1(){

System.err.println("method1——run");

}//公有方法

public voidmethod2(String param){

System.err.println("method1=2——run :"+param);

}

@OverridepublicString toString() {return "Proson{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

实例化对象的方式

通过new关键字与反射相互对比加深对反射的认识,详解代码如下:

//不用反射: 创建对象,需要手动new对象不能动态创建。//new的时候根据new的类名寻找字节码文件,加载进入内存,创建Class对象,并接着创建对应的Proson对象。

Proson p=newProson();//通过反射:只需要一个名字,就可以创建对象。

String className="com.xiaoli.bean.Proson";//寻找该名称的类文件,加载进内存,并创建Class对象。

Class clazz =Class.forName(className);//通过Class对象的newInstance()创建类对象。

Object o = clazz.newInstance();

调用有参构造方法初始化变量

通过有参构造对比反射,详解代码如下:

//不用反射:通过构造方法实例化并初始化变量

Object obj1=new Proson("name",18);

System.err.println("不用反射: "+obj1);//通过反射:Class对象的getConstructor方法拿到构造器。

Constructor constructor = clazz.getConstructor(String.class, Integer.class);//通过构造器的newInstance方法实例化并初始化变量

Object obj2=constructor.newInstance("name2",22);

System.err.println("通过反射: "+obj2);

得到结果

(三) Class 类中方法详解

到这里应该理解到Class对反射的重要性了吧?那么Class类中有什么常用方法呢?

获取公共构造器 getConstructors()

获取所有构造器 getDeclaredConstructors()

获取该类对象 newInstance()

获取类名包含包路径 getName()

获取类名不包含包路径 getSimpleName()

获取类公共类型的所有属性 getFields()

获取类的所有属性 getDeclaredFields()

获取类公共类型的指定属性 getField(String name)

获取类全部类型的指定属性 getDeclaredField(String name)

获取类公共类型的方法 getMethods()

获取类的所有方法 getDeclaredMethods()

获得类的特定公共类型方法: getMethod(String name, Class[] parameterTypes)

获取内部类 getDeclaredClasses()

获取外部类 getDeclaringClass()

获取修饰符 getModifiers()

获取所在包 getPackage()

获取所实现的接口 getInterfaces()

通过一些例子来演示以上常用方法,详解代码如下。

//这里方便操作演示用第二种发方法获取字节码对象

Class clazz2=Proson.class;//通过反射调用有参构造函数初始化对象(上面演示过)

Constructor constructor = clazz2.getConstructor(String.class, Integer.class);

Object obj= constructor.newInstance("lixiaoli", 18);//获得类完整的名字

String className1 =clazz2.getName();

System.err.println("1类完整的名字: "+className1);//获得类名不包含包路径

String className2 =clazz2.getSimpleName();

System.err.println("2类名不含路径: "+className2);//获得类中公共类型(public)属性

Field[] fields =clazz2.getFields();

String fieldName="";for(Field field : fields){

fieldName+=field.getName()+" ";

}

System.err.println("3类中公共属性: "+fieldName);//获得类中全部类型(包括私有)属性

Field[] fieldsAll =clazz2.getDeclaredFields();

fieldName="";for(Field field : fieldsAll){

fieldName+=field.getName()+" ";

}

System.err.println("4类中全部属性: "+fieldName);//获得公共指定属性值

Field age = clazz2.getField("age");

Object o=age.get(obj);

System.err.println("5公共指定属性: "+o);//获得私有指定属性值

Field name = clazz2.getDeclaredField("name");//Field name = clazz2.getField("name");只能获取共有属性 故此方法会抛出NoSuchFieldException异常,所以选用getDeclaredField();

name.setAccessible(true); //设置为true才能获取私有属性

Object o2 =name.get(obj);

System.err.println("6类中私有指定属性值: "+o2);//获取类所有公共类型方法 这里包括 Object 类的一些方法

Method[] methods =clazz2.getMethods();

String methodsName="";for(Method method : methods){

methodsName+=method.getName()+" ";

}

System.err.println("7类公共类型方法: "+methodsName);//获取该类中的所有方法(包括私有)

Method[] methodsAll =clazz2.getDeclaredMethods();

methodsName="";for(Method method : methodsAll){

methodsName+=method.getName()+" ";

}

System.err.println("8类中的所有方法: "+methodsName);//获取并使用指定方法

Method method1 = clazz2.getDeclaredMethod("method1");//获取无参私有方法

method1.setAccessible(true);//设置为true才能获取私有方法

method1.invoke(obj);//调用无参方法

Method method2= clazz2.getMethod("method2",String.class);//获取有参数方法

method2.invoke(obj,"666");//调用有参方法

运行结果

四 反射总结

熟练的使用反射能让我们的程序耦合度降低,当然会损失一部分性能,毕竟有失才有得。

以上就是我对Java反射机制的学习和理解,如果有错误,望指出,以便及时更正!谢谢!

————————————————

原文链接:https://blog.csdn.net/qq_44614710/article/details/86741226

java反射源码_java反射技术详解附源码相关推荐

  1. python开发技术详解pdf下载_python开发技术详解附源码-python开发技术详解电子书pdf下载高清去水印版-精品下载...

    Python开发技术详解适合Python爱好者.大中专院校的学生.社会培训班的学生以及用Python语言进行系统管理.GUI开发.Web开发.数据库编程.网络编程的人员使用. 内容提要 Python是 ...

  2. python嗅探工具详解附源码(使用socket,带tkinter界面)

    python嗅探工具详解(带tkinter界面) 点击详见原理 点击详见原理 TCP/IP协议号补充 必备基础知识 IP数据包格式 详见点此 TCP报文格式 详见点此 struct模块 在Python ...

  3. java配置文件实现方式_java相关:详解Spring加载Properties配置文件的四种方式

    java相关:详解Spring加载Properties配置文件的四种方式 发布于 2020-4-29| 复制链接 摘记: 一.通过 context:property-placeholder 标签实现配 ...

  4. java获取枚举索引_Java枚举使用详解

    在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的"数 ...

  5. java for新循环_Java for循环详解

    Java for循环详解 for 语句是应用最广泛.功能最强的一种循环语句.大部分情况下,for 循环可以代替 while 循环.do while 循环. for 语句是一种在程序执行前就要先判断条件 ...

  6. 直播APP开发 社交直播平台源码搭建——流媒体技术详解

    随着移动互联网的发展,国内也涌现大大小小十几款视频直播app.以王思聪投资的17在2015年的爆红为代表,视频移动直播浮出水面,再到后来的映客.花椒.蜜友圈等等,直播自媒体时代的快速发展改变了人们传统 ...

  7. java学生管理系统代码_java学生信息管理系统(附源码)

    一:   介绍 1:实现登录界面 2:实现主界面 有两种操作 一种是按钮操作  另外一种是SQL语句. 3:连接SQL server 2008 数据库 用到的软件及环境SQLserver2008,ec ...

  8. windows驱动开发资料(《windows驱动开发技术详解》)+源码

    链接:https://pan.baidu.com/s/1db1sEsIMf3YWuxQ090ih_g 提取码:m4lz

  9. Java set的区别_Java Set集合详解及Set与List的区别

    Set是什么? Java中的Set集合是继承Collection的接口,是一个不包含重复元素的集合. 下图是Set集合的源码. Set和List都是以接口的形式来进行声明.Set主要包含三种存放数据类 ...

最新文章

  1. C++知识点46——类继承中的类型转换与访问权限控制(中)
  2. 【笔记】Linux就该这么学-第六课第四章
  3. 过冰点自定义日期时间
  4. 使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案(转)
  5. hdu 5045 费用流
  6. (转)jquery插件Validate的使用
  7. JavaScript编码encode和decode escape和unescape
  8. mysql全局变量 error_记录——node-mysql连接池遇到的全局变量问题
  9. 论文浅尝 | 利用知识图谱嵌入和图卷积网络进行长尾关系抽取
  10. php注册树模式,php设计模式-注册树模式
  11. 请问android直接post请求登录地址成功后,webview还是现实登录界面
  12. 一个物理CPU如何划分成多个虚拟CPU
  13. oracle 删除用户命令和部分表空间操作
  14. C语言和Python语言有什么区别呢?
  15. pythonsample_python sample code | 学步园
  16. 通俗易懂的方式讲解最大流和最小割问题
  17. db2数据库常见问题处理
  18. A股市场周内效应研究
  19. linux查看云锁密码命令,Linux安装云锁
  20. Flutter tween动画

热门文章

  1. 小程序开发 宽度100%_这是您作为开发人员可以实现100%年度目标的方式
  2. 使用Zeigarnik效应来学习编码更快
  3. html上传文件与后台处理,HTML加一般处理程序实现文件上传
  4. Scrapy-redis分布式爬虫
  5. Django查询数据
  6. Python二叉树的三种深度优先遍历
  7. 多站点IIS的架设:主机头法
  8. 漫步最优化三十七——共轭梯度法
  9. oppoR17手机计算机的隐藏功能,OPPO R17 Pro隐藏了很多你不知道的黑科技,让你高效使用手机...
  10. leetcode —— 1013. 将数组分成和相等的三个部分