【 java 反射下篇】java反射机制不难吧?来看看这篇

news/2023/6/6 3:53:58

📋 个人简介

  • 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜
  • 📝 个人主页:馆主阿牛🔥
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:java 小白到高手的蜕变🍁
  • 💬格言:要成为光,因为有怕黑的人!🔥
    请添加图片描述

目录

    • 📋 个人简介
  • 前言
    • 通过反射创建对应的运行时类对象
    • 通过反射获取运行时类的内部结构(了解)
      • 提供结构丰富的People
      • 获取运行时类的属性结构
      • 获取运行时类的方法结构
      • 获取运行时类的构造器结构
      • 获取运行时类的父类以及父类的泛型
      • 获取运行时类的接口,包,注解等
    • 通过反射调用运行时类的内部结构(重要)
      • 调用运行时类中的指定构造器
      • 调用运行时类中的指定属性
      • 调用运行时类中的指定方法
  • 结语

前言

本篇我将总结如何使用反射调用类的内部结构!

通过反射创建对应的运行时类对象

public static void main(String[] args) throws Exception {Class<People> cl = People.class;// newInstance():调用此方法创建对应的运行时类对象// java9之后,这个方法过期了,应使用getConstructor().newInstance()// 也就是先调用空参构造器,然后newInstance()创建对象People obj = cl.getConstructor().newInstance();System.out.println(obj);}

在这里插入图片描述
要想此方法正常的创建运行时类的对象,要求:
1.运行时类必须提供空参的构造器
2.空参的构造器的访问权限得够。通常,设置为 public 。
在 javabean 中要求提供一个 public 的空参构造器。原因:
1.便于通过反射,创建运行时类的对象
2.便于子类继承此运行时类时,默认调用 super ()时,保证父类有此构造器

通过反射获取运行时类的内部结构(了解)

提供结构丰富的People

这里提供一个结构丰富的People类用于下面的测试!

package java反射;import java.io.Serializable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;// 父类
class Creature<T> implements Serializable{private char sex;public double weight;private void breath(){System.out.println("呼吸");}public void eat(){System.out.println("吃东西");}
}
// 接口
interface Myinterface{void info();
}// 注解
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{String value() default "hello";
}
// 子类
@MyAnnotation(value="hi")
public class People extends Creature<String> implements Comparable<String>,Myinterface {private String name;int age;public int id;public People(){}@MyAnnotation(value="aniu")private People(String name) {this.name = name;}People(String name, int age) {this.name = name;this.age = age;}@MyAnnotationprivate void show(String nation){System.out.println("国籍:" + nation);}public String display(String interests){return interests;}@Overridepublic String toString() {return "People{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(String o) {return 0;}@Overridepublic void info() {System.out.println("我是一个人!");}
}

这个结构中有继承,注解,接口,泛型,以及不同权限的属性和方法等,接下类我们通过反射来获取这些结构学习!

获取运行时类的属性结构

public static void main(String[] args) {Class cls = People.class;// 获取属性结构// getFields():获取当前运行时类及其父类中声明为public的访问权限的属性Field[] fields = cls.getFields();for (Field item:fields){System.out.println(item);}System.out.println("------------------------------------");// getDeclaredFields():获取当前运行时类中生申明的所有属性(不包含父类中的属性)Field[] declaredFields = cls.getDeclaredFields();for (Field item:declaredFields){System.out.println(item);// 属性的权限修饰符 数据类型 变量名 也可单独获取到// 1.权限修饰符int modifiers = item.getModifiers();System.out.print(Modifier.toString(modifiers) + "\t");// 2.数据类型Class type = item.getType();System.out.print(type.getName() + "\t");// 3.变量名String name = item.getName();System.out.print(name);System.out.println("\n");}}

在这里插入图片描述

获取运行时类的方法结构

public static void main(String[] args) {Class cls = People.class;// getMethods() 获取当前运行时类以及父类中声明为public的方法Method[] methods = cls.getMethods();for(Method m:methods){System.out.println(m);}System.out.println("--------------------------");// getDeclaredMethods() 获取当前运行时类声明的所有方法(不包含父类)Method[] declaredMethods = cls.getDeclaredMethods();for(Method m:declaredMethods){System.out.println(m);// 方法也可以获取方法申明的注解 权限修饰符 返回值类型 方法名 形参列表 抛出的异常// 这里我只写一下获取方法的注解Annotation[] annotations = m.getAnnotations();for(Annotation a : annotations){System.out.println(a);}}}

在这里插入图片描述

获取运行时类的构造器结构

和上面的一样
getConstructors()和getDeclaredConstructors();,我不再写案例!

获取运行时类的父类以及父类的泛型

package java反射;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;/*** @Author:Aniu* @Date:2023/1/17 21:35* @description 获取运行时类的父类以及父类的泛型*/
public class Demo4 {public static void main(String[] args) {Class<People> cls = People.class;// getSuperclass() 获取运行时类的父类Class<? super People> superclass = cls.getSuperclass();System.out.println(superclass);System.out.println("--------------");// getGenericSuperclass() 获取运行时类的带泛型的父类Type genericSuperclass = cls.getGenericSuperclass();System.out.println(genericSuperclass);System.out.println("--------------");// 获取运行时类的带泛型的父类的泛型ParameterizedType genericSuperclass1 = (ParameterizedType) genericSuperclass;Type[] actualTypeArguments = genericSuperclass1.getActualTypeArguments();System.out.println(actualTypeArguments[0].getTypeName());}
}

在这里插入图片描述

获取运行时类的接口,包,注解等

package java反射;import java.lang.annotation.Annotation;/*** @Author:Aniu* @Date:2023/1/17 21:43* @description 获取运行时类的接口,包,注解等*/
public class Demo5 {public static void main(String[] args) {Class<People> cls = People.class;// getInterfaces() 获取运行时类实现的接口 ,获取父类实现的接口:cls.getSuperclass().getInterfaces();Class<?>[] interfaces = cls.getInterfaces();for(Class c : interfaces){System.out.println(c);}System.out.println("------------------");// getPackage() 获取运行时类所在的包Package aPackage = cls.getPackage();System.out.println(aPackage);System.out.println("------------------");// getAnnotations() 获取运行时类的注解Annotation[] annotations = cls.getAnnotations();for(Annotation a : annotations){System.out.println(a);}}
}

在这里插入图片描述

通过反射调用运行时类的内部结构(重要)

调用运行时类中的指定构造器

package java反射;import java.lang.reflect.Constructor;/*** @Author:Aniu* @Date:2023/1/19 17:00* @description 调用运行时类中的指定构造器*/
public class Demo8 {public static void main(String[] args) throws Exception {Class<People> cls = People.class;// 1.获取指定构造器// getDeclaredConstructor 参数:构造器的参数列表Constructor<People> declaredConstructor = cls.getDeclaredConstructor(String.class);// 2.保证此构造其实可访问的declaredConstructor.setAccessible(true);// 3.调用此构造器创建对象People p = declaredConstructor.newInstance("aniu");System.out.println(p);}
}

在这里插入图片描述
jdk9之后我们用这种方式创建运行时类的对象!即调用空参构造器创建运行时类的对象!

调用运行时类中的指定属性

package java反射;import java.lang.reflect.Field;/*** @Author:Aniu* @Date:2023/1/19 16:15* @description 调用运行时类中的指定属性*/
public class Demo6 {public static void main(String[] args) throws Exception {Class<People> cls = People.class;// 创建运行时类的对象People p = cls.getConstructor().newInstance();// 获取指定的属性 getField()要求运行时类的属性权限修饰符为public// 通常不用此方法Field id = cls.getField("id");// 设置当前属性的值// set(): 参数:1:指明设置那个对象的属性  参数2:将此属性值设置为多少id.set(p,10);// 获取当前属性的值// get(): 参数1:获取那个对象当前的属性值int pid = (int) id.get(p);System.out.println(pid);System.out.println("--------------");// 1.获取指定的属性 通常用getDeclaredFieldField name = cls.getDeclaredField("name");// 2.保证当前属性是可访问的 (对于private和默认权限的属性,设置和获取之前都要加这个)name.setAccessible(true);// 3.设置指定对象的此属性值name.set(p,"aniu");// 4.获取指定对象的此属性值String s = (String) name.get(p);System.out.println(s);}
}

在这里插入图片描述

调用运行时类中的指定方法

package java反射;import java.lang.reflect.Method;/*** @Author:Aniu* @Date:2023/1/19 16:39* @description 调用运行时类中的指定方法*/
public class Demo7 {public static void main(String[] args) throws Exception {Class<People> cls = People.class;// 创建运行时类的对像People p = cls.getConstructor().newInstance();// 1.获取指定的某个方法   getMethod只能获取public// getDeclaredMethod所有权限方法都可获取。参数一:指明获取的方法的名称 参数二:指明获取的方法的形参列表Method show = cls.getDeclaredMethod("show", String.class);// 2. 保证当前方法可访问show.setAccessible(true);// 3. 调用方法// invoke() 参数一:方法的调用者 方法二:给方法的参数// invoke() 方法的返回值即为调用的类中方法的返回值Object c = show.invoke(p, "China");System.out.println(c);}
}

在这里插入图片描述
那如何调用静态方法呢?我给People类加一个静态方法:

public static void print(){System.out.println("我是阿牛!");}
Method print = cls.getDeclaredMethod("print");
print.setAccessible(true);
print.invoke(People.class); // 静态方法可以用类名直接调用

结语

如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。

🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4572778.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

计算机专业生物信息学方向怎么样,2019年生物信息学本科专业怎么样?

2019年本科生物信息学专业怎么样&#xff1f;就业方向和就业前景如何&#xff1f;专业代码&#xff1a;071003修业年限:四年学科门类&#xff1a;理学专业类&#xff1a;生物科学类生物信息学专业怎么样?生物信息学专业近3年就业率情况生物信息学专业男女比例情况生物信息学专…

普渡大学计算机科学本科,普渡大学计算机科学专业怎么样 排名申请条件介绍...

普渡大学(Purdue University)成立于1869年&#xff0c;位于印第安纳州的西拉法叶市&#xff0c;普渡大学美国著名的公里综合研究型大学&#xff0c;也是远近闻名的理工科老牌院校&#xff0c;也是世界工科十强大学之一&#xff0c;今天就要给大家介绍一下普渡大学计算机科学专业…

计算机专业主要学什么?

一、计算机应用技术专业&#xff0c;要学什么&#xff1f; 计算机应用技术专业培养具备管理学理论基础、计算机技术知识及应用能力&#xff0c;掌握信息管理、信息系统分析与设计方法等方面的知识与能力。 未来能在各类企、事业单位、金融机构及政府部门从事信息采集、组织、…

aws ecs 理解任务和容器的资源分配

参考资料 如何在 Amazon ECS 中为任务分配内存&#xff1f; 关于 Amazon ECS 中的 CPU 分配&#xff0c;我需要了解哪些信息&#xff1f; Amazon ECS CloudWatch 指标 任务定义参数 在ecs中可以指定资源的分配逻辑&#xff0c;其实就是cpu和内存分配。 下面这张图对ecs任…

汉源高科2个万兆光口16个千兆光口工业级以太网交换机机架式光纤自愈环网以太网交换机

1&#xff0c;数据控制&#xff1a;支持802.3X全双工流控&#xff0c;支持网络风暴抑制 2&#xff0c;冗余网络&#xff1a;支持STP/RSTP/MSTP&#xff0c;支持符合G.8032(ERPS)标准的以太环网保护技术&#xff08;自愈时间<30ms&#xff09;&#xff0c;保障网络的稳定性 3…

交换机光口总是DOWN状态

端口协商失败 1、故障现象&#xff1a;交换机链接PTN的接口一直处于DOWN状态2、解决过程&#xff1a;&#xff08;1&#xff09;检查物理层设备检测发现光路正常&#xff08;2&#xff09;更换光模块设备还是处于DOWN状态&#xff08;3&#xff09;通过dis interface GigabitEt…

Linux软件安装及管理程序

Linux安装及管理程序Linux软件安装及管理程序一、Linux应用程序基础二、RPM软件包管理工具2.1、RPM介绍2.2、RPM命令三、源码编译安装四、yum安装Linux软件安装及管理程序 一、Linux应用程序基础 应用程序与系统命令的关系 角色系统命令应用程序文件位置般在/bin和/sbin目录…

如果你突然打了个喷嚏,那

作者 | 杨旭东知乎那一定是AB效果不好 ---------测试集涨点猛如虎&#xff0c;推上线无收益&#xff1f;算法新手翻车原因盘点&#xff01;在推荐算法领域&#xff0c;时常会出现模型离线评测效果好&#xff0c;比如AUC、准召等指标大涨&#xff0c;但上线后业务指标效果不佳&a…