java 反射Reflection;Class类

Cindy ·
更新时间:2024-11-14
· 625 次阅读

1.反射机制概述

java能够反射的前提:已经加载过这个类
反射可以通过类名来寻找这个类的所有相关信息、类似于人类的记忆,事先在记忆中有了这个事物的信息,人就可以通过名字来在记忆中寻找事物的具体信息。

Reflection(反射)
是被视为动态语言的关键,反射机制允许程序在执行期借助Reflection API取得任何类的内部信息并能直接操作任意对象的内部属性及方法。

java反射机制所提供的功能
生成动态代理
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法生成动态代理

java反射机制的研究及应用
反射相关的主要API:

java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造方法

2.Class类

Class类可以对任意的类进行高度抽象,能够描述所有的类
在Object类中定义了以下的方法,此方法将被所有子类继承:
public final Class getClass()
以上方法返回值类型就是一个Class类,此类事java反射的源头,实际上所谓反射从程序运行结果来看也很好理解,即:可以通过对象反射求出类的名称

1.Class c0=Person.class; 通过类名.Class可以创建指定类的class实例(Person是类名) 2.Class c1=p.getClass(); 通过一个类的实例对象.getClass()方法,获取对应实例对象的类的Class实例 Class clazz = p.getClass(); Class对象中就包含对象P所属的Person类的所有信息 3.通过Class的静态方法forName(String className)来获取class实例,*这个是获取class实例的常用方法* forName(String className)方法中的参数是你要获取的class实例的类的全路径(包名.类名) try { Class c2=Class.forName("fanshe.Person"); } catch (Exception e) { e.printStackTrace(); } 注意:Class c2=Class.forName("fanshe.Person")语句存在异常,需要捕获异常 3.1反射获取一个子类的父类和接口

代码演示:*
在这里插入图片描述

public class Test1 { public static void main(String[] args) { try { //通过包名,类名的字符串,调用class.forName方法获取指定类的实例 Class clazz= Class.forName("fanshe.Student"); Class superClazz= clazz.getSuperclass();//获取父类 System.out.println("父类"+superClazz.getName()); Class interfaces[]=clazz.getInterfaces();//获取当前类的所有接口 for(Class c:interfaces){ System.out.println("接口"+c.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 运行结果: 父类fanshe.Person 接口fanshe.Move 接口fanshe.Study 3.2反射获取构造方法

在这里插入图片描述

public class Test1 { public static void main(String[] args) { try { Class clazz= Class.forName("fanshe.Student"); Constructor cons[]=clazz.getConstructors();//构造方法的一个数组 //getConstructors获取到类的公有的构造方法 for(Constructor c:cons){ System.out.println("构造方法名称"+c.getName()+"的修饰符是"+c.getModifiers());//获取方法名称 //getModifiers取得方法的修饰符,返回数字1代表public返回数字2代表private } Constructor cons1[]=clazz.getDeclaredConstructors();//获取类的所有构造方法,包括公有和私有的 for(Constructor c:cons1){ System.out.println("构造方法名称"+c.getName()+"的修饰符是"+c.getModifiers()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 运行结果: 构造方法名称fanshe.Student的修饰符是1 构造方法名称fanshe.Student的修饰符是1 构造方法名称fanshe.Student的修饰符是2 构造方法名称fanshe.Student的修饰符是1 构造方法名称fanshe.Student的修饰符是1 `` Class clazz= Class.forName("fanshe.Student"); Constructor cons[]=clazz.getConstructors(); for(Constructor c:cons){ System.out.println("构造方法名称"+c.getName()+"的修饰符是"+c.getModifiers()); //构造方法的参数类型 Class paramClazz[]=c.getParameterTypes(); for(Class pc: paramClazz){ System.out.println("构造方法"+c.getName()+"的参数类型"+pc.getName()); } } 运行结果: 构造方法名称fanshe.Student的修饰符是1 构造方法fanshe.Student的参数类型java.lang.String 构造方法名称fanshe.Student的修饰符是1 3.3通过反射创建一个对象

在这里插入图片描述

import java.lang.reflect.Constructor; import java.lang.reflect.Parameter public class Test1 { public static void main(String[] args) { try { Class clazz=Class.forName("fanshe.Student"); //clazz.newInstance()相当于调用Student类的无参公有构造方法,返回的是Object对象 Object obj=clazz.newInstance(); //强制类型转换 Student stu=(Student)obj; System.out.println(stu.school); //指定获取有一个参数并且为String类型的公有的构造方法 Constructor c=clazz.getConstructor(String.class); //通过newInstace实例化对象,相当于调用调用的是public Student(String school)方法 Student stu1=(Student)c.newInstance("圣芙蕾雅学园"); System.out.println(stu1.school); /*通过反射机制可以强制调用私有的构造方法*/ //指定获取有二个参数的构造方法 Constructor c1=clazz.getDeclaredConstructor(String.class,int.class); c1.setAccessible(true);//解除封装,下面可以对私有方法强制调用 Student stu2=(Student)c1.newInstance("TeRiRi",14); } catch (Exception e) { e.printStackTrace(); } } } 运行结果: 调用的是public Student() null 调用的是public Student(String school) 圣芙蕾雅学园 调用的是private Student(String name,int age) 3.4反射机制获取类的方法

study类中的方法
在这里插入图片描述
test类

package fanshe; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Parameter; public class Test1 { public static void main(String[] args) { try { Class clazz=Class.forName("fanshe.Student"); //获取到类的所有公有方法 Method ms[]=clazz.getMethods(); //获取类的所有方法包括公有私有 /* Method ms[]=clazz.getDeclaredMethods();*/ for(Method m:ms){ System.out.println("方法名"+m.getName()); System.out.println("返回值类型"+m.getReturnType()); System.out.println("修饰符"+m.getModifiers()); Class pcs[]= m.getParameterTypes();//获取方法的参数类型,方法有几个参数数组就有几个元素 if(pcs!=null&&pcs.length>0){ for(Class pc:pcs){ System.out.println("参数类型"+pc.getName()); } } System.out.println("--------------------------"); } } catch (Exception e) { e.printStackTrace(); } } } 运行结果: 方法名showInfo 返回值类型void 修饰符1 -------------------------- 方法名studyInfo 返回值类型void 修饰符1 -------------------------- 方法名movetype 返回值类型void 修饰符1 -------------------------- 方法名wait 返回值类型void 修饰符273 参数类型long -------------------------- ...... 3.5反射机制获取类的属性和包

在这里插入图片描述
在这里插入图片描述

public class Test1 { public static void main(String[] args) { try { Class clazz=Class.forName("fanshe.Student"); Field fs[]=clazz.getFields();//获取类的公有属性,包含父类的公有属性 /*Field fs[]=clazz.getDeclaredFields();//获取本类所有的属性,包括私有*/ for(Field f:fs){ System.out.println("修饰符"+f.getModifiers()); System.out.println("属性的类型"+f.getType()); System.out.println("属性的名称"+f.getName()); } Package p=clazz.getPackage();//获取类所在的包 System.out.println(p.getName()); } catch (Exception e) { e.printStackTrace(); } } } 运行结果: 修饰符1 属性的类型class java.lang.String 属性的名称name fanshe 3.6反射机制调用指定方法

在这里插入图片描述

public class Test1 { public static void main(String[] args) { try { Class clazz=Class.forName("fanshe.Student"); /* 注意:下面无论是反射调用setInfo还是test方法 都调用的是obj对象费方法,obj对象实际上是Student对象 */ Constructor con=clazz.getConstructor();//获取无参构造 Object obj=con.newInstance();//使用无参构造创建对象 //得到名称叫setInfo,参数是String,String的公有方法 Method m=clazz.getMethod("setInfo",String.class,String.class); //使用m.invoke();调用指定方法 m.invoke(obj,"kiana","圣芙蕾雅学园");//参数1是需要实例化的对象,后面的参数是调用当前方法的实际参数 //如果想要调用一个私有方法,需要解除封装 Method m1=clazz.getDeclaredMethod("test",String.class);//获取方法名为test,参数为1个String类型的方法 m1.setAccessible(true);//解除封装可以强制调用私有方法 m1.invoke(obj,"TeRiRi"); //调用一个重载方法 Method m2=clazz.getMethod("setInfo",int.class);//重载方法 m2.invoke(obj,14); //有返回值的方法 Method m3=clazz.getMethod("getSchool");//获取方法名为getSchool并且没有方法 String school=(String)m3.invoke(obj);//调用没有有回值但是没有参数的方法 System.out.println(school); } catch (Exception e) { e.printStackTrace(); } } } 运行结果: 调用的是public Student() 这是个setInfo(String name,String school)方法 这是私有方法 这是setInfo(int age)方法 圣芙蕾雅学园 3.7调用指定属性

在这里插入图片描述

public class Test1 { public static void main(String[] args) { try { Class clazz=Class.forName("fanshe.Student"); //反射创建一个对象 Constructor con=clazz.getConstructor(); Student stu=(Student)con.newInstance(); /*等效于 Object obj=con.newInstance(); Student stu=(Student)obj; */ Field f=clazz.getField("school");//获取名称为school的属性 f.set(stu,"圣芙蕾雅学园");//对stu对象的school属性设置值,“圣芙蕾雅学园” String school=(String)f.get(stu);//获取stu对象的school属性值,返回值类型为Object System.out.println(school); //如果是私有属性 Field f1=clazz.getDeclaredField("privateField"); f1.setAccessible(true); f1.set(stu,"测试私有属性"); System.out.println(f1.get(stu)); } catch (Exception e) { e.printStackTrace(); } } } 运行结果: 调用的是public Student() 圣芙蕾雅学园 测试私有属性
作者:VioletEvgarden



class类 JAVA class

需要 登录 后方可回复, 如果你还没有账号请 注册新账号