反射与Class类

(所有源代码已经上传到码云上:https://gitee.com/c3h2/knowledge-study.git 该章节所属reflect包中,具体代码开编号,每个类都有编号)

1.1 反射简介

在Java之中,反射就是其中最重要的特性之一,也正是因为Java支持反射,才使得Java的设计更加灵活,这么多年也一直经久不衰的原因之一(抗高并发也是一个原因)。如果你不掌握反射,那么在Java里面很难走的通,也写不出高复用的代码,因为几乎所有的框架都是基于反射来实现的。

既然Java反射如此的重要,那么什么是Java反射呢,Java反射中的“反”又是什么意思呢?观察如下代码(源码reflect.cn.tansanqinger.basics.Test1.java):

public class Test1 {public static void main(String[] args) {Class<?> clazz = new java.util.Date().getClass();System.out.println(clazz);//直接输出,详细描述所有信息System.out.println(clazz.getName());//获取类完整的包名信息System.out.println(clazz.getSimpleName());//获取类名}
}

上述代码运行结果为

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bqi8pmfK-1600683885467)(C:\Users\C3H2\AppData\Roaming\Typora\typora-user-images\image-20200921113201484.png)]

上述代码获取了Date类的相关信息,包括类路径和类名,相当于是通过一个名称,将它的底完全挖掘出来了。能够获取到类的包名,那么我们就可以实现不导包而将类进行实例化操作,这样就降低了耦合。

1.2 获取Class类对象实例

在Java反射中用于获取Class类对象实例的方式有三,他们分别是:

  • 第一种:利用Object类提供的getClass()方法,通过实例化对象调用获得

  • 第二种:利用“类.class”的原生方式来获得

  • 第三种:通过Class类中提供的方法进行实例化

上述获取实例的new java.util.Date().getClass() 也可以修改为java.util.Date.class,前者利用Object中的getClass()方法来获取Class类的实例,实际上需要对通过指定类的实例化对象来完成,但是后者可以在没有指定类实例化对象的时候直接获取Class实例,相比之前节约了一个实例化对象。

除此之外,还有Class内部提供的一个forName方法,利用该方法也可以实现Class的实例化,该方法的定义为:

public static Class<?> forName(String className) throws ClassNotFoundException

使用此方法需要注意的是,要书写正确的类路径和类名,否则将会抛出ClassNotFoundException这个异常。

三种方式都很重要,因此都需要掌握

  • getClass():需要通过明确的获得使用类的实例化对象;

  • 类.class:需要明确的进行操作类的导入处理;

  • Class.forName():可以通过字符串描述要使用类的名称;

三种不同方式在开发中的使用如下(源码reflect.cn.tansanqinger.basics.Test2.java):

public class Test2 {public static void main(String[] args) throws ClassNotFoundException {Class<?> clsA = java.util.Date.class;Class<?> clsB = Class.forName("java.util.Date");Class<?> clsC = new java.util.Date().getClass();System.out.println(clsA);System.out.println(clsB);System.out.println(clsC);System.out.println(clsA.getName());System.out.println(clsB.getName());System.out.println(clsC.getName());System.out.println(clsA.getSimpleName());System.out.println(clsB.getSimpleName());System.out.println(clsC.getSimpleName());}
}

运行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b41DzvtN-1600683885474)(C:\Users\C3H2\AppData\Roaming\Typora\typora-user-images\image-20200921132410798.png)]

1.3 反射与类操作

上述说了Java反射的三种使用方式,这一节来分析一下反射与类的操作,首先看一组方法

序号 方法名称 类型 说明
1 public Package getPackage() 方法 获取程序所在的包名称
2 public Class<? super T> getSuperclass() 方法 获取所继承的父类
3 public Class<?>[] getInterfaces() 方法 获取所有的父接口
4 public Constructor **getConstructor(Class<?>… parameterTypes) ** throws NoSuchMethodException, SecurityException 方法 根据指定的参数类型获取指定的构造方法(public)
5 public Class<?>[] getConstructors() throws SecurityException 方法 获取类中的所有的构造方法(public)
6 public Constructor getDeclaredConstructor(Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException 方法 获取一个类中指定的构造方法(public、protected、default)
7 public Constructor<?>[] **getDeclaredConstructors() **throws SecurityException 方法 获取一个类中的全部构造方法(public、protected、default)
8 public Method[] getDeclaredMethods() throws SecurityException 方法 获取本类中的所有方法
9 public Method getDeclaredMethod(String name, Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException 方法 获取本类一个指定类型的Method实例
10 public Method getMethod(String name, Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException 方法 获取一个公共的方法,包括父类的方法
11 public Field[] getFields() throws SecurityException 方法 获取所有继承来的public成员
12 public Field getField(String name) throws NoSuchFieldException, SecurityException 方法 获取一个指定类型的成员
13 public Field[] getDeclaredFields() throws SecurityException 方法 获取本类定义的全部的成员
14 public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException 方法 获取一个本类定义成员
15 public Class<?> getType() 获取属性类型
16 public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException 获取属性内容
17 public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException 设置属性内容
18 public void setAccessible(boolean flag) 取消封装

上述的所有的方法就是Java反射中重要的方法,当然还有很多的方法,这里就不一一列举了,如果你有兴趣,可以直接去查看源代码JDK12文档了解更多。

同时需要注意的一件事:使用反射进行类实例化在jdk1.9之后发生了变化。我们可以通过官网的源代码来了解这一变化。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gLJt8oyo-1600683885477)(C:\Users\C3H2\AppData\Roaming\Typora\typora-user-images\image-20200921172320288.png)]

下面演示一下这些方法的使用(源代码reflect.cn.tansanqinger.basics.Test3.java):

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
interface IMessage{}
interface IChannel{}
abstract class AbstraceChannalMessage implements IMessage,IChannel{public void AbstractChannelMessage() {}public void AbstractChannelMessage(String username, String password) {}
}
//该类为定义方法,但是可以获取继承来的方法
class Person{}
class CloudMessage extends AbstraceChannalMessage implements IMessage,IChannel{public CloudMessage() {}public CloudMessage(String url, String userName, String password) {}
}
public class Test3 {public static void main(String[] args) {Class<?> clazzA = CloudMessage.class;System.out.println("【获取包的名称】"+clazzA.getPackage().getName());System.out.println("【获取继承父类】"+clazzA.getSuperclass().getName());System.out.println("【获取实现接口】"+ Arrays.toString(clazzA.getInterfaces()));//---------------获取构造方法----------------Class<?> clazzB = CloudMessage.class;Constructor<?> constructor[] = clazzB.getDeclaredConstructors();for(Constructor<?> cont : constructor) {System.out.println(cont);}//-------------获取方法--------------Class<?> clazz = Person.class;Method methods[] = clazz.getMethods();for(int i = 0 ; i < methods.length ; i ++) {System.out.print(Modifier.toString(methods[i].getModifiers())+" ");System.out.print(methods[i].getReturnType().getName()+" ");System.out.print(methods[i].getName()+"(");Class<?> params[] = methods[i].getParameterTypes();//获取所有参数for(int x = 0 ; x < params.length ; x++) {System.out.print(params[x].getSimpleName()+" arg-"+x);if(x<params.length -1) {System.out.print(",");}}System.out.print(") ");Class<?> exps[] = methods[i].getExceptionTypes();if(exps.length > 0) {System.out.print("throws ");for(int x = 0 ; x < exps.length ; x++) {System.out.print(exps[x].getSimpleName());if(x <params.length -1) {System.out.print(",");}}}System.out.println();}}
}

剩下几个类似的使用方法,这里就不细说了。

1.4Unsafe工具类

为了进一步对反射进行扩展,Java提供了一个Unsafe类,该类位于sun.misc包之中,该类主要的功能就是通过反射来获取对象,打破JVM的固定对象使用模式,该类直接通过C++对数据进行读取,这个类可以在没有实例化对象的时候进行类中方法的调用。

构造方法:private Unsafe() {}

常量:private static final Unsafe theUnsafe = new Unsafe();

由于构造方法被私有化了,因此该类需要通过内部定义的“theUnsafe”常量对象来进行Unsafe类的调用。使用方法如下(源代码reflect.cn.tansanqinger.basics.Test4.java):

class Singleton{private Singleton(){System.out.println("构造方法被私有化");}public void msg(){System.out.println("www.tansanqinger.cn");}
}
public class Test4 {public static void main(String[] args) {try{Field unsafe = Unsafe.class.getDeclaredField("theUnsafe");unsafe.setAccessible(true);Unsafe unsafe1 = (Unsafe) unsafe.get(null);Singleton singleton = (Singleton) unsafe1.allocateInstance(Singleton.class);singleton.msg();} catch (Exception e){}}
}

现在可以发现利用Unsafe类可以打破已有的JVM中关于对象的使用的模型,可以在没有实例化对象的时候直接调用类中所提供的普通方法,但是这样的操作表示的处理全部由程序自己完成,而所有的代码不受到JVM的控制,也就意味着所有的垃圾回收机制就将失效。
提出意义:Unsafe只是提供了一种底层的直接进行对象操作的支持,与实际的开发意义不大。如果在以后笔试的过程里面要求你编写单例设计模式的时候,请你注意如下几点:要使用懒汉式单例设计、要针对于数据的同步做出处理、补充上利用Unsafe可以绕过对象的实例化机制,直接调用类中的方法。

谈谈Java中的反射与Class等类相关推荐

  1. 谈谈Java中的反射机制

    前言 在使用框架进行开发时,我们的开发速度大大提升.我们感叹于它的神奇之处,我们使用它的时候,也要知道其"灵魂".正所谓,无反射,不框架,框架的灵魂就是反射. 另外,我们在ecli ...

  2. 谈谈JAVA中的安全发布

    谈谈JAVA中的安全发布 昨天看到一篇文章阐述技术类资料的"等级",看完之后很有共鸣.再加上最近在工作中越发觉得线程安全性的重要性和难以捉摸,又掏出了<Java并发编程实战& ...

  3. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  4. java中的反射(一)

    在java中反射是指在运行期动态的获取类型的信息,比如接口的信息,类的方法和成员变量.反射的入口是Class类下面我们来一起了解一下这个Class类. 在java中每个已加载的类都有一个类信息,每个对 ...

  5. Java 中使用反射来创建对象、调用方法

    Java 中使用反射来创建对象.调用方法 反射创建对象 反射调用方法 反射调用私有方法 反射调用可变参私有方法 反射调用的方法自身可以抛出异常的情形   假设已有下面的类: import java.l ...

  6. java代码安全检测机制_全面解析:java中的反射机制,内含代码验证解析

    什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功 ...

  7. 深入理解Java中的反射技术

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

  8. 谈谈java中成员变量与成员方法继承的问题

    谈谈java中成员变量与成员方法继承的问题 关于成员变量和成员方法的的继承问题,我也可以做一个小测试,来看看结果. 首先我们先创建一个父类: 其次再创建一个子类,子类中要比父类中少一个成员方法: 这样 ...

  9. formdata 接受参数中带有class 对象_浅析JAVA中的反射机制及对Servlet的优化

    今天来聊聊java中的反射机制,工作以后发现很多东西动不动就要使用反射或者动态代理,如果不能很好的理解反射,那么对于动态代理等一些重要的设计模式就会有种不够通透的感觉. 所谓的反射,就是在运行状态中, ...

最新文章

  1. RDLC SubReports Exporting to Excel Are Ignored
  2. 28-Interview-面试
  3. 高性能的索引实现——《深究MySQL》
  4. Scrapy保存到txt文件或者数据库里面
  5. java算法之冒泡排序
  6. U盘/硬盘/移动硬盘专家
  7. java大数 bigin_Java大数操作
  8. 数组元素替换_LeetCode基础算法题第183篇:一维数组的重新洗牌
  9. 关于Kubernetes规划的灵魂N问
  10. 十字链表表示矩阵c语言,十字链表法,十字链表压缩存储稀疏矩阵详解
  11. CMMB 全国各地市频率规划表
  12. R语言---相关系数
  13. 英汉对照:32个最富哲理的名言警句
  14. VBA数据类型和类型转换函数
  15. 上海自动驾驶再上热搜,为什么是它?丨曼孚科技
  16. 霹雳火s毕老师_$_Java笔记(一)
  17. 纽约摄影教材Tips
  18. 思科模拟器配置静态路由(下一跳使用端口)
  19. 对于网站的用户访问行为的简单分析 - 2
  20. Docker构建Shipyard

热门文章

  1. jwt生成和解密-jose4j
  2. Java多线程(二)
  3. window10闹钟不解释
  4. C# 货币金额中文(英文)大写转换方法-工具类
  5. 中易项目管理系统,辅助项目经理规范管理项目的小助手
  6. LaTeX中PPT如何添加动态效果?
  7. Problem - 1190B - Codeforces(分类讨论博弈)
  8. windows 10 中 java 设置path不起作用
  9. 打印word文档时遇到标记区如何取消
  10. 概率检索模型+模糊k近邻+粒子群优化算法(PSO)