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

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中,不同电脑的配置和操作系统(如Win11与Win7)可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行,需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下,使LabVIEW开发的程序保持稳定运行的有效策略。 LabVIEW版本兼容性 LabVIEW各版本对不同操作系统的支持存在差异。因此,在开发程序时,尽量使用

如何在运行时修改serialVersionUID

优质博文:IT-BLOG-CN 问题 我正在使用第三方库连接到外部系统,一切运行正常,但突然出现序列化错误 java.io.InvalidClassException: com.essbase.api.base.EssException; local class incompatible: stream classdesc serialVersionUID = 90314637791991

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

遮罩,在指定元素上进行遮罩

废话不多说,直接上代码: ps:依赖 jquer.js 1.首先,定义一个 Overlay.js  代码如下: /*遮罩 Overlay js 对象*/function Overlay(options){//{targetId:'',viewHtml:'',viewWidth:'',viewHeight:''}try{this.state=false;//遮罩状态 true 激活,f

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大,但不同的语言在不同领域都有着自己的优势,为了强强联合,LabVIEW提供了强大的外部程序接口能力,包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等。通过DLL可以使用户很方便地调用C、C++、C#、VB等编程语言写的程序以及windows自带的大