Java反射机制的简单讲解
作者:_Yoke 发布时间:2023-12-12 20:49:13
🌱1. 什么是反射机制?
首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
简单说,反射机制值得是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
🌱2. java反射机制提供了什么功能?
在运行时能够判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任一对象的方法
在运行时创建新类对象
🌱3.new和反射创建有什么区别呢?
new: 静态编译,在编译期就将模块编译进来,执行该字节码文件,所有的模块都被加载;
反射:动态编译,编译期没有加载,等到模块被调用时才加载;
注:spring的ioc就用到反射机制,newInstance创建。更加的通用,并且降低耦合,避免了硬编码,只需提供一个字符串就可以动态的创建。
String className = readfromXMlConfig;//从xml 配置文件中获得字符串
Class c = Class.forName(className);
factory = (AInterface)c.newInstance();
举例:
有自行车🚲,小轿车🚗,
静态:上班将自行车放车里去上班,一定得带着,一个不能落下,
动态:将自行车放家里,交通堵塞骑自行车去,车放家里。
🌱4. 如何通过反射调用私有对象?
Field[] declaredFields = clazz.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println("属性的名称:" + f.getName());
System.out.println("属性的类型:" + f.getType().getName());
// 给属性赋值
f.setAccessible(true);// 设置为私有属性可以访问
🌱5.如何通过反射调用方法?
Method m = stuClass.getMethod("show1", String.class);
System.out.println(m);
//实例化一个Student对象
Object obj = stuClass.getConstructor().newInstance();
m.invoke(obj, "刘德华");
🌱6. class类一部分常用方法总结
获取公共构造器 getConstructors()
获取所有构造器getDeclaredConstructors
获取包含的方法 getMethod()
获取包含的属性 getField(String name)
获取内部类 getDeclaredClasses()
获取外部类getDeclaringClass()
获取所实现的接口 getInterfaces()
获取修饰符 getModifiers()
获取所在包 getPackage()
获取类名包含包路径 getName()
java反射的简单演示
package com.fjh;
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
System.out.println("实例化一个对象!");
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
package com.fjh;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException,
SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
// 普通方法创建一个对象
Student stu = new Student();
// 利用反射机制创建一个对象
Student newInstance = Student.class.newInstance();
// 通过字节码获取属性
Class clazz = Student.class;
// Field field = clazz.getField("name");//指定返回一个公有的属性
Field field = clazz.getDeclaredField("name");
System.out.println("属性的名称:" + field.getName());
System.out.println("属性的类型:" + field.getType().getName());
System.out.println("---------------------");
// 获取一个类中的所有属性
Field[] declaredFields = clazz.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println("属性的名称:" + f.getName());
System.out.println("属性的类型:" + f.getType().getName());
// 给属性赋值
f.setAccessible(true);// 设置为私有属性可以访问
if (int.class == f.getType()) {
f.set(newInstance, 50);
} else if (String.class == f.getType()) {
f.set(newInstance, "蔡徐坤");
}
}
System.out.println("========通过直接赋值后的结果==========");
System.out.println(newInstance);
System.out.println("========获取所有方法==========");
// 获取所有方法 不包括构造方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
String methodName = method.getName();// 参数名称
int parameterCount = method.getParameterCount();// 参数个数
System.out.println("方法名字:" + methodName);
System.out.println("方法参数个数:" + parameterCount);
Class<?>[] parameterTypes = method.getParameterTypes();
// 获取每个方法的参数类型
for (Class<?> class1 : parameterTypes) {
System.out.println("参数类型:" + class1.getName());
}
// 获取方法的返回值
Class<?> returnType = method.getReturnType();
System.out.println("方法的返回值为:" + returnType.getName());
System.out.println("-------------------");
}
// 执行获取到的 方法
// 如果方法参数有多个,则需要用字节码数组来代替
// Method declaredMethod = clazz.getDeclaredMethod("setName", new
// Class[]{String.class,int.class});
// 执行方法同样使用数组
// declaredMethod.invoke(newInstance,Object[]{"mayun",20} );
Method declaredMethod = clazz.getDeclaredMethod("setName", String.class);// 返回当前Class对象表示的类或接口的指定已说明的一个方法对象。
declaredMethod.invoke(newInstance, "马云");
System.out.println("==========设值注入=========");
System.out.println(newInstance);
// 构造函数
Constructor constructor = clazz.getConstructor(new Class[] { String.class, int.class });
// 如何执行构造函数
Object obj = constructor.newInstance(new Object[] { "周杰伦", 46 });
System.out.println("==========构造注入=========");
System.out.println(obj);
System.out.println("==========构造方法=========");
//获取所有的构造函数
Constructor[] constructors = clazz.getConstructors();
for (Constructor c : constructors) {
if(c.getParameterCount() != 0){
Class[] parameterTypes = c.getParameterTypes();
for (Class class1 : parameterTypes) {
System.out.println("参数类型:"+class1.getTypeName());
}
System.out.println("-------------------");
}else{
System.out.println("无参构造");
System.out.println("-------------------");
}
}
}
}
🌱7. 结果
来源:https://blog.csdn.net/qq_40896997/article/details/94483820
猜你喜欢
- paras.xml文件<?xml version="1.0" encoding="UTF-8"
- SingleClick:@Retention(AnnotationRetention.RUNTIME)@Target(AnnotationT
- SpringBoot2之PUT请求接收不了参数的解决办法,这个问题,关乎两个Filter过滤器,是spring3和3.5之后提供的,目的就是
- 本文实例讲述了Java获得当前时间前指定几个小时具体时间的方法。分享给大家供大家参考,具体如下:package getBeforeHourD
- 如何配置 * step1: 自定义 * /** * 自定义 * */public class MyInterceptor implemen
- 栈和队列:都是线性表,都是基于List基础上的实现线性表:数组,链表,字符串,栈,队列元素按照一条“直线&rdq
- Spring注入方式可以分为三类,xml注入、注解注入、BeanDefinition注入;用法上可以分为三种,但是底层实现代码都是统一Bea
- 本文实例讲述了Spring实战之使用注解实现声明式事务操作。分享给大家供大家参考,具体如下:一 配置文件<?xml version=&
- 一、使用Optional引言1.1、代码问题引出在写程序的时候一般都遇到过 NullPointerException,所以经常会对程序进行非
- 按照官方文档进行的配置:快速开始|mybatis-plus引入依赖:<!-- 引入mybatisPlus --> &
- 1 概念方面List是接口,ArrayList是List接口的一个实现类2 初始化方面2.1 List2.1.1 错误写 * ist list
- 目录目标为什么操作步骤工程截图运行效果完整源代码目标在SpringBoot中集成内存数据库H2.为什么像H2、hsqldb、derby、sq
- 配置不生效的解决办法注意:如果配置不生效,则说明spring优先加载了其他配置:解决办法:添加启动参数 -Dlogging.config=c
- Spring Boot 自动装配最重要的注解@SpringBootApplication@Target(ElementType.TYPE)@
- 目录Sonar概述一、 搭建sona服务二、idea配置三、 配置maven的setting.xml文件四、idea中 mvn sonar:
- Map集合和Collection集合的区别Map集合是有Key和Value的,Collection集合是只有Value。Collection
- UI 妹纸又给了个图叫我做,我一看是这样的:我们首先把这个控件划分成 几个部分:1.底下部分的直线 :2.左右两边的半圆
- ThreadLocal简介变量值的共享可以使用public static的形式,所有线程都使用同一个变量,如果想实现每一个线程都有自己的共享
- Servlet3.0的出现是servlet史上最大的变革,其中的许多新特性大大的简化了web应用的开发,为广大劳苦的程序员减轻了压力,提高了
- 在软件开发过程中经常需要知道程序运行的大概时间,或者需要在规定时间内取数据,这是可以使用下面的方法获取时间段,还可以用在限时循环方法一:/*