笔记:反射

追寻自由的路途 追寻自由的路途     2022-08-29     166

关键词:

反射库提供了大量操作Java代码的工具集,以便编写能够通道操作Java代码的程序,能够分析类能力的程序称为反射(reflective)。

  1. Class

    在程序运行期间,Java运行时系统始终为所有的对象维护一个称为运行时的类型标识,这个信息跟踪着每个对象所属的类,虚拟机利用运行时类型信息选择相应的方法执行,可以通过专门的类来访问这些信息,保存这些信息的类被称为 Class,Object 类的getClass方法将返回一个Class类型的实例,示例代码如下:

    ??????public static void main( String[] args )

    ????????{

    ????????????????String str = "测试号";

    ????????????????Class stringClassObj = str.getClass();

    ???????????????? ?

    ????????????????System.out.println("Str Class is "+stringClassObj.getName());

    ????????}

    可以调用静态方法 forName 获得类名对应得Class对象,示例代码如下:

    String className = "java.util.Date";

    Class cl = Class.forName(className);

    虚拟机为每个类型管理一个Class对象,因此可以利用 == 运算符实现两个类对象得比较操作,还可以使用 newInstance 方法调用默认的构造函数初始化新创建的对象,示例代码如下:

    if(stringClassObj.getClass() == String.getClass()){

    ????...

    }

    ? ?

    String className = "java.util.Date";

    Object m = Class.forName(className).newInstance();

    如果没有默认的构造函数,则调用类对象的 newInstance 会抛出异常,如果希望调用构造函数来创建实例,则必须使用 Constructor类的 newInstance 方法。

  2. 利用反射分析类的能力

    在Java的 java.lang.reflect包中有三个类 Field、Method和Constructor类,分别用于描述类的域、方法和构造器,三个类都有一个叫做getName的方法,用来返回项目的名称。Field类有一个getType方法,用来返回描述域所属类型的Class对象;Method Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法,这三个类都有getModifiers的方法,返回一个整数值,用不同的位开关描述public static 这样的修饰符,通过 Modifier类的 isPublic、isPrivate isFinal 来判断方法的修饰符。

    Class类中的 getFields、getMethods和getConstructors 方法分别返回类提供的 public 域、方法和构造器;getDeclareFields、getDeclareMethods getDeclaredConstructors 方法将分别返回类中声明的全部域、方法和构造器,其中包括私有、保护成员,但不包括超类(基类)的成员,示例代码如下:

    public class App {

    ????public static void main(String[] args) {

    ????????Class clazz = Double.class;

    ????????Field[] fields = clazz.getFields();

    ????????Method[] methods = clazz.getMethods();

    ????????String clazzDeclare = BuildClassCode(clazz);

    ????????System.out.println(clazzDeclare);

    ????????System.out.println("{");

    ????????for (Field f : fields) {

    ????????????System.out.println(" " + BuildFieldCode(f));

    ????????}

    ? ?

    ????????System.out.println("");

    ????????for (Method m : methods) {

    ????????????System.out.println(" " + BuildMethodCode(m));

    ????????}

    ????????System.out.println("}");

    ????}

    ? ?

    ????/**

    ???? * 构建类源码

    ???? * @param clazz

    ???? * @return

    ???? */

    ????protected static <T> String BuildClassCode(Class<T> clazz) {

    ????????StringBuilder sb = new StringBuilder();

    ???????? int modifiers = clazz.getModifiers();

    ?????????sb.append(Modifier.toString(modifiers) + " ");

    ?????????sb.append(clazz.getSimpleName() + " ");

    ???????? ?

    ?????????Class superClass = clazz.getSuperclass();

    ?????????if (superClass != null && superClass != Object.class) {

    ?????????????sb.append("extends " + superClass.getSimpleName());

    ?????????}

    ???????? ?

    ?????????Class[] superInterfaces = clazz.getInterfaces();

    ?????????if (superInterfaces != null && superInterfaces.length > 0) {

    ?????????????sb.append(" implements ");

    ???????? ?

    ?????????????for (int j = 0; j < superInterfaces.length; j++) {

    ?????????????????sb.append(superInterfaces[j].getName());

    ???????? ?

    ?????????????????if (j != superInterfaces.length - 1) {

    ?????????????????????sb.append(", ");

    ?????????????????}

    ?????????????}

    ?????????}????????

    ???????????????return sb.toString();

    ????}

    ? ?

    ????/**

    ???? * 构建公共字段域代码

    ???? * @param field

    ???? * @return

    ???? */

    ????protected static String BuildFieldCode(Field field) {

    ????????StringBuilder sb = new StringBuilder();

    ? ?

    ????????int mod = field.getModifiers();

    ????????sb.append(Modifier.toString(mod) + " ");

    ????????sb.append(field.getType().getSimpleName() + " " + field.getName() + ";");

    ? ?

    ????????return sb.toString();

    ????}

    ? ?

    ????/**

    ???? * 构建公共方法代码

    ???? * @param method

    ???? * @return

    ???? */

    ????protected static String BuildMethodCode(Method method) {

    ????????StringBuilder sb = new StringBuilder();

    ? ?

    ????????int mod = method.getModifiers();

    ????????sb.append(Modifier.toString(mod) + " ");

    ????????sb.append(method.getReturnType().getSimpleName() + " " + method.getName());

    ????????sb.append("(");

    ????????Class[] parameterTypes = method.getParameterTypes();

    ????????for (int i = 0; i < parameterTypes.length; i++) {

    ????????????Class c = parameterTypes[i];

    ????????????sb.append(c.getName());

    ? ?

    ????????????if (i != parameterTypes.length - 1) {

    ????????????????sb.append(", ");

    ????????????}

    ????????}

    ????????sb.append(")");

    ? ?

    ????????return sb.toString();

    ????}

    }

  3. 在运行时使用反射分析对象

    查看对象域的关键方法是Field类中的get方法,如果 f 是一个Field类型的对象,obj是某个包含 f 域的类对象,f.get(obj)将返回一个对象,其值为obj域的当前值,如果访问的时私有域,get方法的调用将抛出一个 IllegalAccessException 异常,反射机制默认行为受限与Java的访问控制,如果需要覆盖Java的访问控制,可以调用Field、Method和Constructor对象的setAccessible方法,示例代码如下:

    ????????Employee em = new Employee();

    ????????em.setName("lixue");

    ????????em.setYear(1982);

    ????????em.setMonth(12);

    ????????em.setDay(7);

    ???????? ?

    ????????Field nameField = em.getClass().getDeclaredField("name");

    ????????// 覆盖访问控制,允许访问私有字段域

    ????????nameField.setAccessible(true);

    ???????? ?

    ????????Object val = nameField.get(em);

    ????????System.out.println("Employee name is "+val);

  4. 使用反射编写泛型数组代码

    可以使用Array类的newInstance方法构造新数组,调用他必须提供二个参数,一个时数组的元素类型,一个是数组的长度,示例代码如下:

    Object newArray = Array.newInstance(componentType,newLength);

  5. 调用任意方法

    在Method类中有一个invoke方法,他允许调用包装在当前Method对象中的方法,invoke的方法签名是:

    Object invoke(Object obj,Object... args)

    第一个参数是隐式参数,其余的对象提供了显示参数,对于静态方法,第一个参数可以被忽略,可以设置为 null,示例代码如下:

    ????????Method getNameMethod = em.getClass().getDeclaredMethod("getName", null);

    ????????String nameValue = (String) getNameMethod.invoke(em);

    ????????System.out.println("Employee name is "+nameValue);

    ? ?

? ?

java讲课笔记36:初探反射机制

文章目录零、本讲学习目标一、认识反射(一)Java反射机制(二)Java反射的动态性质(三)如何理解Java反射的原理(四)利用反射可实现的功能二、Java反射常用API三、使用反射的基本步骤四、利用反射获取类的信息(一)获... 查看详情

狂神说java笔记--反射和注解部分笔记(代码片段)

传送门==>B站遇见狂神说–反射和注解笔记和练习只是跟着视频整理的;但是有的知识点并没有整理进来.ml1.什么是注解2.内置注解3.元注解4.自定义注解5.反射概述6.获得反射对象7.获取Class类的方式8.所有类型的Class对象9.类... 查看详情

笔记:反射

反射库提供了大量操作Java代码的工具集,以便编写能够通道操作Java代码的程序,能够分析类能力的程序称为反射(reflective)。Class 类在程序运行期间,Java运行时系统始终为所有的对象维护一个称为运行时的类型标识,这个... 查看详情

java学习笔记-反射机制

1. JAVA反射机制的概念 2.怎样实例化一个Class对象    Class.forName(包名.类名);  对象.getClass();  类.class;  ============================代码========================== 查看详情

java反射基础笔记

...反射的基础,该系列为笔者学习慕课反射讲解视频的学习笔记,尽可能全的记录,以帮助初学者快速掌握反射基础知识,如需转载该系列请注明原文 查看详情

反射简单笔记

1.反射基本概念: 01.定义:反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性!  02.作用:001.在运行期间获取类的修饰符,包名,类名,实现的接口,继承的父类。002.在运行期间获取类... 查看详情

反射的笔记

1.反射基本概念: 01.定义:反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性!  02.作用:001.在运行期间获取类的修饰符,包名,类名,实现的接口,继承的父类。002.在运行期间获取类... 查看详情

javaweb学习笔记11_xml&反射

解析XML总结(SAX、Pull、Dom三种方式)反射的简单介绍:反射1、什么是反射技术?动态获取指定类以及类中的内容(成员),并运行其内容。应用程序已经运行,无法在其中进行new对象的建立,就无法使用对象。这时可以根据配置... 查看详情

java学习笔记之反射

鲁春利的工作笔记,谁说程序员不能有文艺范?Java程序在运行期间可以动态加载、解析和使用一些在编译阶段并不确定的类型,这一机制被称为反射(Reflection)或自省(Introspection)。Java程序可以加载一个运行时才得知名称的cl... 查看详情

javase学习笔记之反射技术(二十四)

反射技术:其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员。简单说:反射技术可以对一个类进行解剖。 反射的... 查看详情

java学习注解和反射超详细笔记(代码片段)

目录一、注解1、注解入门2、内置注解3、自定义注解,元注解二、反射机制1、Java反射机制概念1.1静态&动态语言1.2反射机制概念1.3反射机制研究与应用1.4反射机制优缺点1.5实现2、理解Class类并获取Class实例2.1class类介绍2.2获取Cla... 查看详情

java基础笔记14

1.反射.Class:反射类任何一个类都有一个Class反射类.(影子)java.lang.reflect.*; Field:字段类 Method:方法类类 Constructor:构造方法类. 2.获取反射类//1.获取反射类类名.class Classclazz1=People.class; //2.通过全类名 Classclazz2=Class.forName("demo.People 查看详情

go语言学习笔记—进阶—反射:反射的类型对象(reflect.type)—什么是反射?

反射的定义反射是指在程序运行时,对程序本身进行访问和修改的能力。在编译程序时,变量被转换为内存地址,变量名不会被编译器写入到可执行部分;在运行程序时,程序又无法获取自身信息支持反射的... 查看详情

java反射机制笔记

概念:类和对象之间的关系--》类是对象的一种描述,对象是一类实物的一个具体实例子 反射:得到元数据的行为,得到类中所有成员和行为德尔一种机制 Class是对一切类的行为和状态的抽象 Class类:用于描述一切类/接口/枚举/... 查看详情

go语言学习笔记—进阶—反射:反射的类型对象(reflect.type)(代码片段)

在Go中,我们可以通过reflect.TypeOf()函数获得任意值的类型对象(reflect.Type),go程序通过类型对象(reflect.Type)可以访问任意值的类型信息。packagemainimport( "fmt" "reflect" "testing" 查看详情

day23jvm与反射的学习笔记

JVM:-----------------1.JVM:javavirtualmachine.2.classfile *.class3.ClassLoader4.runtimedataarea运行时数据区。1.Methodarea:方法区.(shared)供所有线程共享.2.heap(shared):供所有线程共享.3.javastack(栈区)独占的。4.nativemethodstac 查看详情

go语言学习笔记—进阶—反射:反射的类型对象(reflect.type)—使用反射获取结构体的成员变量类型(代码片段)

对指针变量获取反射类型对象时,通过reflect.Elem()方法,获取指针变量指向的元素类型,即取元素,等效于对指针变量做一个*操作。packagemainimport( "fmt" "reflect" "testing")funcmain() typecatstruct ins: 查看详情

《javascript高级程序设计》学习笔记|9.2.代理捕获器与反射方法

关注前端小讴,阅读更多原创技术文章代理捕获器与反射方法代理可以捕获13种不同的基本操作,代理对象上执行的任一种操作只会有一种捕获处理程序被调用,不存在重复捕获现象只要在代理上操作,所有捕获器都会拦截对应... 查看详情