
#https://blog.csdn.net/a745233700/article/details/82893076(参考)
一、 基本概念
通常情况下编写代码都是固定的,无论运行多少次执行的结果也是固定的,在某些特殊场合中编写
代码时不确定要创建什么类型的对象,也不确定要调用什么样的方法,这些都希望通过运行时传递
的参数来决定,该机制叫做动态编程技术,也就是反射机制。
通俗来说,反射机制就是用于动态创建对象并且动态调用方法的机制。
目前主流的框架底层都是采用反射机制实现的。
如:
Person p = new Person(); - 表示声明Person类型的引用指向Person类型的对象
p.show(); - 表示调用Person类中的成员方法show
二、 Class类
(1) 基本概念
- java.lang.Class类的实例可以用于描述Java应用程序中的类和接口,也就是一种数据类型。
- 该类没有公共构造方法,该类的实例由Java虚拟机和类加载器自动构造完成,本质上就是加载到内
-
(2) 获取Class对象的方式
使用数据类型.class的方式可以获取对应类型的Class对象(掌握)。
- 使用引用/对象.getClass()的方式可以获取对应类型的Class对象。
- 使用包装类.TYPE的方式可以获取对应基本数据类型的Class对象。
- 使用Class.forName()的方式来获取参数指定类型的Class对象(掌握)。
- 使用类加载器ClassLoader的方式获取指定类型的Class对象。
(3) 常用的方法(掌握)


(4)创建对象的两种方式
原始创建~
反射创建~
注意:newInstance的方法已经过时了,所以在通过Constuctor去实例化对象(在“三”中有讲解) ```java package task20;
import java.io.*; import java.util.Scanner; import java.util.UUID;
public class ClassTest { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException { //1,使用原始方式实例化对象 Person p1=new Person(); System.out.println(“无参创建的方式是:”+p1); //0 null //2,使用反射的方式实例化对象,此时是直接给定了一个类类型 Class<?> c1=Class.forName(“task20.Person”); c1.newInstance(); System.out.println(“反射方式实例化对象:”+c1.newInstance());
//也可以通过键盘输入Scanner sc=new Scanner(System.in);String str1=sc.next();Class<?> c2=Class.forName(str1);System.out.println("从键盘输入的对象实例化:"+c2);//由此我们也可以知道,还能从配置文件中读取输入BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("d:/a.txt")));String str=br.readLine();Class<?> c3=Class.forName(str);System.out.println("从配置文件中读取的对象实例化"+c3.newInstance());br.close();}
}
<a name="j7chh"></a># <a name="UxyVD"></a># 三、Constructor类<a name="lRG3b"></a>## (1)基本概念- java.lang.reflflect.Constructor类主要用于描述获取到的构造方法信息<a name="ioJsu"></a>## (2)Class类的常用方法<a name="VPEtD"></a>## (3)使用Constructor无参构造实例化对象```javapackage task20;import java.io.*;import java.lang.reflect.Constructor;import java.util.Scanner;import java.util.UUID;public class ClassTest {public static void main(String[] args) throws Exception {//1,使用原始方式实例化对象Person p1=new Person();System.out.println("无参创建的方式是:"+p1); //0 null//2,使用反射的方式实例化对象,此时是直接给定了一个类类型Class<?> c1=Class.forName("task20.Person");//c1.newInstance();//System.out.println("反射方式实例化对象:"+c1.newInstance());Constructor<?> constructor = c1.getConstructor();System.out.println("无参方式创建的对象:"+constructor.newInstance());/* //也可以通过键盘输入Scanner sc=new Scanner(System.in);String str1=sc.next();Class<?> c2=Class.forName(str1);System.out.println("从键盘输入的对象实例化:"+c2);//由此我们也可以知道,还能从配置文件中读取输入BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("d:/a.txt")));String str=br.readLine();Class<?> c3=Class.forName(str);System.out.println("从配置文件中读取的对象实例化"+c3.newInstance());*/}}
(4)使用有参构造方法实例化对象


(5)Constructor类的常用方法
(5)获取类中的所有构造方法的参数信息
Constructor<?>[] constructors = c1.getConstructors();for (Constructor ct:constructors) {System.out.println("构造方法的访问修饰符是:"+ct.getModifiers());System.out.println("构造方法的名称为:"+ct.getName());System.out.println("参数类型是:");Class[] parameterTypes = ct.getParameterTypes();for (Class ps:parameterTypes) {System.out.println(ps);}}
四、Field类
(1)基本概念
java.lang.reflflect.Field类主要用于描述获取到的单个成员变量信息
(2) Class类的常用方法
(3)Field类的常用方法
(4)获取成员变量数值的两种方式
package task20;import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class PersonFieldTest {public static void main(String[] args) throws Exception {//1使用原始的方式获取类的成员变量的信息Person p1=new Person(10,"林三");System.out.println(p1.getName());//1-2如果name为public修饰的,可以直接p1.name访问System.out.println("---------------------------");//2 使用反射机制制造对象,并获取成员变量的数据并打印//2.1 获取Class对象Class<?> aClass = Class.forName("task20.Person");//2.2 根据Clss对象获取(有参)Constructor构造方法Constructor<?> constructor = aClass.getConstructor(int.class, String.class);//2.3 使用有参构造方法得到Person类型的对象Object object = constructor.newInstance(10, "王五");//2.4 根据Class对象获取对应的成员变量信息 name为成员字段的名字Field name1 = aClass.getDeclaredField("name");//2.5 使用person类型的对象获取成员变量的数值并打印 获取对应字段的值System.out.println("获取到的成员变量信息为:"+name1.get(object));}}
(5)修改成员变量数值的两种方式
package task20;import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class PersonFieldTest {public static void main(String[] args) throws Exception {//1使用原始的方式获取类的成员变量的信息Person p1=new Person(10,"林三");System.out.println(p1.getName());//1-2如果name为public修饰的,可以直接p1.name访问System.out.println("---------------------------");//2 使用反射机制制造对象,并获取成员变量的数据并打印//2.1 获取Class对象Class<?> aClass = Class.forName("task20.Person");//2.2 根据Clss对象获取(有参)Constructor构造方法Constructor<?> constructor = aClass.getConstructor(int.class, String.class);//2.3 使用有参构造方法得到Person类型的对象Object object = constructor.newInstance(10, "王五");//2.4 根据Class对象获取对应的成员变量信息 name为成员字段的名字Field field = aClass.getDeclaredField("name");//设置java语言访问检查//field.setAccessible(true);//2.5 使用person类型的对象获取成员变量的数值并打印 获取对应字段的值System.out.println("获取到的成员变量信息为:"+field.get(object));System.out.println("--------------------------------");//3,修改成员变量的值//使用原始方式去进行修改// p1.name="张三";//System.out.println("通过原始方式修改后的值为"+p1.name);//4,使用反射机制修改指定对象成员变量中的值//修改object对象中的成员变量名为field的数值为关羽,即修改Person中name的值为关羽field.set(object,"关羽");System.out.println("通过反射修改的值为"+field.get(object));}}
如果访问的成员变量的修饰符为public,则直接访问和通过反射访问都没问题
如果访问的成员变量的修饰符为private,则不能直接访问,通过反射机制进行访问时,要进行java语言访问检查设置,这个也称为暴力反射。
package task20;import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class PersonFieldTest {public static void main(String[] args) throws Exception {//1使用原始的方式获取类的成员变量的信息Person p1=new Person(10,"林三");System.out.println(p1.getName());//1-2如果name为public修饰的,可以直接p1.name访问System.out.println("---------------------------");//2 使用反射机制制造对象,并获取成员变量的数据并打印//2.1 获取Class对象Class<?> aClass = Class.forName("task20.Person");//2.2 根据Clss对象获取(有参)Constructor构造方法Constructor<?> constructor = aClass.getConstructor(int.class, String.class);//2.3 使用有参构造方法得到Person类型的对象Object object = constructor.newInstance(10, "王五");//2.4 根据Class对象获取对应的成员变量信息 name为成员字段的名字Field field = aClass.getDeclaredField("name");//设置java语言访问检查field.setAccessible(true); /*** 设置!!!***///2.5 使用person类型的对象获取成员变量的数值并打印 获取对应字段的值System.out.println("获取到的成员变量信息为:"+field.get(object));System.out.println("--------------------------------");//3,修改成员变量的值//使用原始方式去进行修改// p1.name="张三";//System.out.println("通过原始方式修改后的值为"+p1.name);//4,使用反射机制修改指定对象成员变量中的值//修改object对象中的成员变量名为field的数值为关羽,即修改Person中name的值为关羽field.set(object,"关羽");System.out.println("通过反射修改的值为"+field.get(object));}}
(6)获取所有成员变量的实现
//5,获取所有成员变量Field[] declaredFields = aClass.getDeclaredFields();for (Field ds:declaredFields) {System.out.println("获取到的成员变量的修饰符为"+ds.getModifiers());System.out.println("获取到的成员变量的类型为"+ds.getType());System.out.println("获取到的成员变量名称为"+ds.getName());System.out.println("---------------------------------------");}
五、Method类
(1)基本概念
java.lang.reflflect.Method类主要用于描述获取到的单个成员方法信息。
(2)Class类的常用方法
(3)Method类的常用方法
(4)获取成员方法的方式
//6,使用反射机制制造对象,并调用方法打印结果// 6.1 使用Class类制造对象Class<?> aClass1 = Class.forName("task20.Person");// 6.2 使用Constructor方法获取有参构造方法Constructor<?> constructor1 = aClass1.getConstructor(int.class, String.class);// 6.3 使用有参的构造方法制造对象Object object2 = constructor1.newInstance(20, "好家伙");// 6.4 根据Class对象获取对象的成员方法Method method=aClass1.getMethod("getName");// 6.5 使用对象调用成员方法并打印 相当于调用object2的getName()方法System.out.println("调用方法的返回是:"+method.invoke(object2));
(5)获取所有成员方法的实现
package com.lagou.task20;import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class PersonMethodTest {public static void main(String[] args) throws Exception {// 1.使用原始方式构造对象并调用方法打印结果Person p1 = new Person("zhangfei", 30);System.out.println("调用方法的返回值是:" + p1.getName()); // zhangfeiSystem.out.println("------------------------------------------------------");// 2.使用反射机制构造对象并调用方法打印结果// 2.1 获取Class对象Class c1 = Class.forName("com.lagou.task20.Person");// 2.2 根据Class对象来获取对应的有参构造方法Constructor constructor = c1.getConstructor(String.class, int.class);// 2.3 使用有参构造方法构造对象并记录Object object = constructor.newInstance("zhangfei", 30);// 2.4 根据Class对象来获取对应的成员方法Method method = c1.getMethod("getName");// 2.5 使用对象调用成员方法进行打印// 表示使用object对象调用method表示的方法,也就是调用getName方法来获取姓名System.out.println("调用方法的返回值是:" + method.invoke(object)); // zhangfeiSystem.out.println("------------------------------------------------------");// 3.使用反射机制来获取类中的所有成员方法并打印Method[] methods = c1.getMethods();for (Method mt : methods) {System.out.println("成员方法的修饰符是:" + mt.getModifiers());System.out.println("成员方法的返回值类型是:" + mt.getReturnType());System.out.println("成员方法的名称是:" + mt.getName());System.out.println("成员方法形参列表的类型是:");Class<?>[] parameterTypes = mt.getParameterTypes();for (Class ct : parameterTypes) {System.out.print(ct + " ");}System.out.println();System.out.println("成员方法的异常类型列表是:");Class<?>[] exceptionTypes = mt.getExceptionTypes();for (Class ct: exceptionTypes) {System.out.print(ct + " ");}System.out.println();System.out.println("---------------------------------------------------");}}}
六、获取其它结构信息

package com.lagou.task20;import java.io.Serializable;@MyAnnotationpublic class Student<T, E> extends Person implements Comparable, Serializable {@Overridepublic int compareTo(Object o) {return 0;}}
package com.lagou.task20;import java.lang.annotation.Annotation;import java.lang.reflect.Type;public class StudentTest {public static void main(String[] args) throws Exception {// 获取Student类型的Class对象Class c1 = Class.forName("com.lagou.task20.Student");System.out.println("获取到的包信息是:" + c1.getPackage());System.out.println("获取到的父类信息是:" + c1.getSuperclass());System.out.println("-------------------------------------------------");System.out.println("获取到的接口信息是:");Class[] interfaces = c1.getInterfaces();for (Class ct : interfaces) {System.out.print(ct + " ");}System.out.println();System.out.println("-------------------------------------------------");System.out.println("获取到的注解信息是:");Annotation[] annotations = c1.getAnnotations();for (Annotation at : annotations) {System.out.print(at + " ");}System.out.println();System.out.println("-------------------------------------------------");System.out.println("获取到的泛型信息是:");Type[] genericInterfaces = c1.getGenericInterfaces();for (Type tt : genericInterfaces) {System.out.print(tt + " ");}System.out.println();}}


