Day68(获取运行时类的完整结构,调用运行时类的指定结构)

2024-02-25 14:18

本文主要是介绍Day68(获取运行时类的完整结构,调用运行时类的指定结构),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

获取运行时类的完整结构

通过反射获取运行时类的完整结构

Field、Method、Constructor、Superclass、Interface、Annotation

  • 实现的全部接口

  • 所继承的父类

  • 全部的构造器

  • 全部的方法

  • 全部的Field

使用反射可以取得:

1.实现的全部接口

  • public Class<?>[] getInterfaces()

确定此对象所表示的类或接口实现的接口。

2.所继承的父类

  • public Class<? Super T> getSuperclass()

返回表示此Class 所表示的实体(类、接口、基本类型)的父类的Class。

3.全部的构造器

  • public Constructor[] getConstructors()

返回此Class 对象所表示的类的所有public构造方法。

  • public Constructor[] getDeclaredConstructors()

返回此Class 对象表示的类声明的所有构造方法。

Constructor类中:

  • 取得修饰符:public int getModifiers();

  • 取得方法名称: public String getName();

  • 取得参数的类型:public Class<?>[] getParameterTypes();

4.全部的方法

  • public Method[] getDeclaredMethods()

  • 返回此Class对象所表示的类或接口的全部方法

  • public Method[] getMethods()

返回此Class对象所表示的类或接口的public的方法

Method类中:

  • public Class<?> getReturnType()取得全部的返回值

  • public Class<?>[] getParameterTypes()取得全部的参数

  • public int getModifiers()取得修饰符

  • public Class<?>[] getExceptionTypes()取得异常信息

5.全部的Field

  • public Field[] getFields()

返回此Class对象所表示的类或接口的public的Field。

  • public Field[] getDeclaredFields()

返回此Class对象所表示的类或接口的全部Field。

Field方法中:

  • public int getModifiers() 以整数形式返回此Field的修饰符

  • public Class<?> getType() 得到Field的属性类型

  • public String getName() 返回Field的名称。

6.Annotation相关

  • get Annotation(Class annotationClass)

  • getDeclaredAnnotations()

7.泛型相关

获取父类泛型类型:Type getGenericSuperclass()

泛型类型:ParameterizedType

获取实际的泛型类型参数数组:getActualTypeArguments()

8.类所在的包Package getPackage()

Persons类

package com.lingxiang.reflection;
@MyAnnotation(value = "hi")
public class Persons extends Creature<String> implements Comparable<String>,MyInterface{private String name;int age;public int id;public Persons(){}@MyAnnotation(value = "abc")private Persons(String name){this.name = name;}Persons(String name,int age){this.name = name;this.age = age;}@MyAnnotationprivate String show(String nation){System.out.println("我的国籍是: " + nation);return nation;}public String display(String interest){return interest;}@Overridepublic void info() {System.out.println("我是一个人");}@Overridepublic int compareTo(String o) {return 0;}
}

父类Creature

package com.lingxiang.reflection;import java.io.Serializable;public class Creature<T> implements Serializable {private char gender;public double weight;private void breath(){System.out.println("生物呼吸");}public void eat(){System.out.println("生物进食");}
}

获取Field

package com.lingxiang.reflection;import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.Modifier;public class FieldTest {@Testpublic void test1(){Class clazz = Persons.class;//获取属性结构//getFields():获取当前运行时类及其父类中声明为public访问权限的属性Field[] fields = clazz.getFields();for (Field f : fields){System.out.println(f);}System.out.println();//getDeclaredFields():获取当前运行时类中声明的所属性。(不包含父类中声明的属性)Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields){System.out.println(f);}}@Test//权限修饰符 数据类型 变量名public void test2(){Class clazz = Persons.class;Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields){//权限修饰符int modifier = f.getModifiers();System.out.print(Modifier.toString(modifier)+"\t");//数据类型Class type = f.getType();System.out.print(type+"\t");//变量名String name = f.getName();System.out.print(name+"\n");}}}

获取Method

package com.lingxiang.reflection;import org.junit.Test;import java.lang.annotation.Annotation;
import java.lang.reflect.Method;public class MethodTest {@Testpublic void test1(){Class clazz = Persons.class;//getMethods():获取当前运行时类及其所父类中声明为public权限的方法Method[] methods = clazz.getMethods();for (Method m : methods){System.out.println(m);}//getDeclaredMethods():获取当前运行时类中声明的所方法。(不包含父类中声明的方法System.out.println();Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods){System.out.println(m);}}@Test//权限修饰符 返回值类型 方法名(参数类型 形参名 ...)Throws XxxException{}public void test2(){Class clazz = Persons.class;Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods){//获取方法声明的注解Annotation[] annotations = m.getAnnotations();for (Annotation a : annotations){System.out.println(a);}}}
}

获取其它

package com.lingxiang.reflection;import org.junit.Test;import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class OtherTest {/*获取构造器结构*/@Testpublic void test1() {Class clazz = Persons.class;//getConstructors():获取当前运行时类中声明为public的构造器Constructor[] constructors = clazz.getConstructors();for (Constructor c : constructors) {System.out.println(c);}//getDeclaredConstructors():获取当前运行时类中声明的所的构造器System.out.println();Constructor[] declaredConstructors = clazz.getDeclaredConstructors();for (Constructor c : constructors) {System.out.println(c);}}@Test/*获取运行时类的父类*/public void test2() {Class clazz = Persons.class;Class superclass = clazz.getSuperclass();System.out.println(superclass);}@Test/*获取运行时类的带泛型的父类*/public void test3() {Class clazz = Persons.class;Type genericSuperclass = clazz.getGenericSuperclass();ParameterizedType paraType = (ParameterizedType) genericSuperclass;Type[] actualTypeArguments = paraType.getActualTypeArguments();for (Type t : actualTypeArguments) {System.out.println(t.getTypeName());}System.out.println(genericSuperclass);}/*获取运行时类实现的接口*/@Testpublic void test4() {Class clazz = Persons.class;Class[] interfaces = clazz.getInterfaces();for (Class c : interfaces) {System.out.println(c);}System.out.println();//获取运行时类的父类实现的接口Class[] interfaces1 = clazz.getSuperclass().getInterfaces();for (Class c : interfaces1) {System.out.println(c);}}/*获取运行时类所在的包*/@Testpublic void test5() {Class clazz = Persons.class;Package pack = clazz.getPackage();System.out.println(pack);}/*获取运行时类声明的注解*/@Testpublic void test6(){Class clazz = Persons.class;Annotation[] annotations = clazz.getAnnotations();for (Annotation a : annotations){System.out.println(a);}}
}

小结:

1.在实际的操作中,取得类的信息的操作代码,并不会经常开发。

2.一定要熟悉java.lang.reflect包的作用,反射机制。

3.如何取得属性、方法、构造器的名称,修饰符等。

调用运行时类的指定结构

1.调用指定方法

通过反射,调用类中的方法,通过Method类完成。步骤:

1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。

2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。

Object invoke(Object obj, Object … args)

说明:

1.Object 对应原方法的返回值,若原方法无返回值,此时返回null

2.若原方法若为静态方法,此时形参Object obj可为null

3.若原方法形参列表为空,则Object[] args为null

4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。

2.调用指定属性

在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。

  • public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。

  • public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。

在Field中:

  • public Object get(Object obj) 取得指定对象obj上此Field的属性内容

  • public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容

关于setAccessible方法的使用

  • Method和Field、Constructor对象都有setAccessible()方法。

  • setAccessible启动和禁用访问安全检查的开关。

  • 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。

    • 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。

    • 使得原本无法访问的私有成员也可以访问

  • 参数值为false则指示反射的对象应该实施Java语言访问检查。

/*** 调用运行时类指定的结构:属性,方法,构造器*/
public class ReflectionTest1 {/*调用指定的属性:*/@Testpublic void test1() throws NoSuchFieldException, IllegalAccessException, InstantiationException {Class clazz = Persons.class;//创建运行时类的对象Persons p = (Persons) clazz.newInstance();//获取指定属性:要求属性声明为public//通常不用此方式Field id = clazz.getField("id");//设置对象的属性值id.set(p, 10);//获取当前属性的值int i = (int) id.get(p);System.out.println(i);}/*
调用指定的属性:*/@Testpublic void test2() throws IllegalAccessException, InstantiationException, NoSuchFieldException {Class clazz = Persons.class;//创建运行时类的对象Persons p = (Persons) clazz.newInstance();//1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性Field name = clazz.getDeclaredField("name");//2.保证当前属性是可访问的name.setAccessible(true);//3.获取、设置指定对象的此属性值name.set(p, "Tom");System.out.println(name.get(p));}/*调用指定的方法:*/@Testpublic void test3() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {Class clazz = Persons.class;Persons p = (Persons) clazz.newInstance();/*1.获取指定的某个方法getDeclaredMethod():参数1 :指明获取的方法的名称  参数2:指明获取的方法的形参列表*/Method show = clazz.getDeclaredMethod("show", String.class);//2.保证当前方法是可访问的show.setAccessible(true);/*3. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参invoke()的返回值即为对应类中调用的方法的返回值。*/Object o = show.invoke(p, "China");System.out.println(o);System.out.println("*************如何调用静态方法*****************");Method showDesc = clazz.getDeclaredMethod("showDesc");showDesc.setAccessible(true);//如果调用的运行时类中的方法没返回值,则此invoke()返回null//Object returnVal = showDesc.invoke(null);showDesc.invoke(Persons.class);}/*调用指定的构造器:*/@Testpublic void test4() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class clazz = Persons.class;/*1.获取指定的构造器getDeclaredConstructor():参数:指明构造器的参数列表*/Constructor constructor = clazz.getDeclaredConstructor(String.class);//2.保证此构造器是可访问的constructor.setAccessible(true);//3.调用此构造器创建运行时类的对象Persons p = (Persons)constructor.newInstance("乌龟");System.out.println(p);}
}

这篇关于Day68(获取运行时类的完整结构,调用运行时类的指定结构)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/745734

相关文章

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

在Ubuntu上打不开GitHub的完整解决方法

《在Ubuntu上打不开GitHub的完整解决方法》当你满心欢喜打开Ubuntu准备推送代码时,突然发现终端里的gitpush卡成狗,浏览器里的GitHub页面直接变成Whoathere!警告页面... 目录一、那些年我们遇到的"红色惊叹号"二、三大症状快速诊断症状1:浏览器直接无法访问症状2:终端操作异常

Spring Boot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)

《SpringBoot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)》本文将以一个实际案例(用户管理系统)为例,详细解析SpringBoot中Co... 目录引言:为什么学习Spring Boot分层架构?第一部分:Spring Boot的整体架构1.1

mybatis直接执行完整sql及踩坑解决

《mybatis直接执行完整sql及踩坑解决》MyBatis可通过select标签执行动态SQL,DQL用ListLinkedHashMap接收结果,DML用int处理,注意防御SQL注入,优先使用#... 目录myBATiFBNZQs直接执行完整sql及踩坑select语句采用count、insert、u

Java发送SNMP至交换机获取交换机状态实现方式

《Java发送SNMP至交换机获取交换机状态实现方式》文章介绍使用SNMP4J库(2.7.0)通过RCF1213-MIB协议获取交换机单/多路状态,需开启SNMP支持,重点对比SNMPv1、v2c、v... 目录交换机协议SNMP库获取交换机单路状态获取交换机多路状态总结交换机协议这里使用的交换机协议为常

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

nodejs打包作为公共包使用的完整流程

《nodejs打包作为公共包使用的完整流程》在Node.js项目中,打包和部署是发布应用的关键步骤,:本文主要介绍nodejs打包作为公共包使用的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言一、前置准备二、创建与编码三、一键构建四、本地“白嫖”测试(可选)五、发布公共包六、常见踩坑提醒