🌱1. 什么是反射机制?
首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
简单说,反射机制值得是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
🌱2. java反射机制提供了什么功能?
在运行时能够判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任一对象的方法
在运行时创建新类对象
🌱3.new和反射创建有什么区别呢?
new: 静态编译,在编译期就将模块编译进来,执行该字节码文件,所有的模块都被加载;
反射:动态编译,编译期没有加载,等到模块被调用时才加载;
注:spring的ioc就用到反射机制,newInstance创建。更加的通用,并且降低耦合,避免了硬编码,只需提供一个字符串就可以动态的创建。
String className= readfromXMlConfig;//从xml 配置文件中获得字符串
Classc= 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()
- 类名不包含包路径
getSimpleName()
java反射的简单演示
package com.fjh;publicclassStudent{private String name;privateint age;public StringgetName(){return name;}publicvoidsetName(String name){this.name= name;}publicintgetAge(){return age;}publicvoidsetAge(int age){this.age= age;}publicStudent(String name,int age){this.name= name;this.age= age;}publicStudent(){
System.out.println("实例化一个对象!");}@Overridepublic StringtoString(){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;publicclassReflectTest{publicstaticvoidmain(String[] args)throws InstantiationException, IllegalAccessException, NoSuchFieldException,
SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException{// 普通方法创建一个对象
Student stu=newStudent();// 利用反射机制创建一个对象
Student newInstance= Student.class.newInstance();// 通过字节码获取属性
Classclazz= 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);}elseif(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(newClass[]{ String.class,int.class});// 如何执行构造函数
Object obj= constructor.newInstance(newObject[]{"周杰伦",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(Classclass1: parameterTypes){
System.out.println("参数类型:"+class1.getTypeName());}
System.out.println("-------------------");}else{
System.out.println("无参构造");
System.out.println("-------------------");}}}}
🌱5. 结果