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

相关文章

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Spring Security中用户名和密码的验证完整流程

《SpringSecurity中用户名和密码的验证完整流程》本文给大家介绍SpringSecurity中用户名和密码的验证完整流程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 首先创建了一个UsernamePasswordAuthenticationTChina编程oken对象,这是S

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景

MySQL 获取字符串长度及注意事项

《MySQL获取字符串长度及注意事项》本文通过实例代码给大家介绍MySQL获取字符串长度及注意事项,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 获取字符串长度详解 核心长度函数对比⚠️ 六大关键注意事项1. 字符编码决定字节长度2

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

springboot项目打jar制作成镜像并指定配置文件位置方式

《springboot项目打jar制作成镜像并指定配置文件位置方式》:本文主要介绍springboot项目打jar制作成镜像并指定配置文件位置方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录一、上传jar到服务器二、编写dockerfile三、新建对应配置文件所存放的数据卷目录四、将配置文

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到