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调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

PyCharm 接入 DeepSeek最新完整教程

《PyCharm接入DeepSeek最新完整教程》文章介绍了DeepSeek-V3模型的性能提升以及如何在PyCharm中接入和使用DeepSeek进行代码开发,本文通过图文并茂的形式给大家介绍的... 目录DeepSeek-V3效果演示创建API Key在PyCharm中下载Continue插件配置Con

如何利用Java获取当天的开始和结束时间

《如何利用Java获取当天的开始和结束时间》:本文主要介绍如何使用Java8的LocalDate和LocalDateTime类获取指定日期的开始和结束时间,展示了如何通过这些类进行日期和时间的处... 目录前言1. Java日期时间API概述2. 获取当天的开始和结束时间代码解析运行结果3. 总结前言在J

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

一分钟带你上手Python调用DeepSeek的API

《一分钟带你上手Python调用DeepSeek的API》最近DeepSeek非常火,作为一枚对前言技术非常关注的程序员来说,自然都想对接DeepSeek的API来体验一把,下面小编就来为大家介绍一下... 目录前言免费体验API-Key申请首次调用API基本概念最小单元推理模型智能体自定义界面总结前言最

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

java获取图片的大小、宽度、高度方式

《java获取图片的大小、宽度、高度方式》文章介绍了如何将File对象转换为MultipartFile对象的过程,并分享了个人经验,希望能为读者提供参考... 目China编程录Java获取图片的大小、宽度、高度File对象(该对象里面是图片)MultipartFile对象(该对象里面是图片)总结java获取图片

Java通过反射获取方法参数名的方式小结

《Java通过反射获取方法参数名的方式小结》这篇文章主要为大家详细介绍了Java如何通过反射获取方法参数名的方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、前言2、解决方式方式2.1: 添加编译参数配置 -parameters方式2.2: 使用Spring的内部工具类 -

Java如何获取视频文件的视频时长

《Java如何获取视频文件的视频时长》文章介绍了如何使用Java获取视频文件的视频时长,包括导入maven依赖和代码案例,同时,也讨论了在运行过程中遇到的SLF4J加载问题,并给出了解决方案... 目录Java获取视频文件的视频时长1、导入maven依赖2、代码案例3、SLF4J: Failed to lo