Java反射机制概念、原理与用法总结
本文实例讲述了Java反射机制概念、原理与用法。分享给大家供大家参考,具体如下:
反射机制是什么
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射机制能做什么
反射机制主要提供了以下功能:
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理。
反射机制的相关API
InterFace接口
packagecom.app; publicinterfaceInterFace{ voidread(); }
Person类
packagecom.app; publicclassPersonimplementsInterFace{ privateStringid; privateStringname; publicStringage; //构造函数1 publicPerson(){ } //构造函数2 publicPerson(Stringid){ this.id=id; } //构造函数3 publicPerson(Stringid,Stringname){ this.id=id; this.name=name; } publicStringgetId(){ returnid; } publicvoidsetId(Stringid){ this.id=id; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicStringgetAge(){ returnage; } publicvoidsetAge(Stringage){ this.age=age; } /** *静态方法 */ publicstaticvoidupdate(){ } @Override publicvoidread(){ } }
获取类:3种方法
packagecom.app; publicclassT1{ publicstaticvoidmain(String[]args){ //第一种方法:forName try{ Class>class1=Class.forName("com.app.Person"); System.out.println(class1); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } //第二张方法:class Class>class2=Person.class; //第三种方法:getClass Personperson=newPerson(); Class>class3=person.getClass(); System.out.println(class2); System.out.println(class3); } }
运行结果:
classcom.app.Person classcom.app.Person classcom.app.Person
获取所有的方法:getMethods()
packagecom.app; importjava.lang.reflect.Method; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //获取所有的公共的方法 Method[]methods=class1.getMethods(); for(Methodmethod:methods){ System.out.println(method); } }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
//自定义方法 publicstaticvoidcom.app.Person.update() publicjava.lang.Stringcom.app.Person.getName() publicvoidcom.app.Person.read() publicjava.lang.Stringcom.app.Person.getId() publicvoidcom.app.Person.setName(java.lang.String) publicvoidcom.app.Person.setId(java.lang.String) //父类Object类方法 publicfinalvoidjava.lang.Object.wait()throwsjava.lang.InterruptedException publicfinalvoidjava.lang.Object.wait(long,int)throwsjava.lang.InterruptedException publicfinalnativevoidjava.lang.Object.wait(long)throwsjava.lang.InterruptedException publicbooleanjava.lang.Object.equals(java.lang.Object) publicjava.lang.Stringjava.lang.Object.toString() publicnativeintjava.lang.Object.hashCode() publicfinalnativejava.lang.Classjava.lang.Object.getClass() publicfinalnativevoidjava.lang.Object.notify() publicfinalnativevoidjava.lang.Object.notifyAll()
获取所有实现的接口:getInterfaces()
packagecom.app; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //获取所有的接口 Class>[]interS=class1.getInterfaces(); for(Class>class2:interS){ System.out.println(class2); } }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
interfacecom.app.InterFace
获取父类:getSuperclass()
packagecom.app; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //获取父类 Class>superclass=class1.getSuperclass(); System.out.println(superclass); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
//父类是Object类 classjava.lang.Object
获取所有的构造函数:getConstructors()
packagecom.app; importjava.lang.reflect.Constructor; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //获取所有的构造函数 Constructor>[]constructors=class1.getConstructors(); for(Constructor>constructor:constructors){ System.out.println(constructor); } }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
publiccom.app.Person(java.lang.String,java.lang.String) publiccom.app.Person(java.lang.String) publiccom.app.Person()
获取所有的属性:getDeclaredFields();
packagecom.app; importjava.lang.reflect.Constructor; importjava.lang.reflect.Field; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //取得本类的全部属性 Field[]field=class1.getDeclaredFields(); for(Fieldfield2:field){ System.out.println(field2); } }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
privatejava.lang.Stringcom.app.Person.id privatejava.lang.Stringcom.app.Person.name
可以看出属性的修饰符是:private,数据类型:String,名字:id/name
创建实例:newInstance()
packagecom.app; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person");; //创建实例化:相当于new了一个对象 Objectobject=class1.newInstance(); //向下转型 Personperson=(Person)object; }catch(ClassNotFoundExceptione){ e.printStackTrace(); }catch(InstantiationExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); } } }
getDeclaredFields和getFields的区别
getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
getFields()获得某个类的所有的公共(public)的字段,包括父类。
小例子
packagecom.app; importjava.lang.reflect.Field; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person");; //获得所有的字段属性:包括 Field[]declaredFields=class1.getDeclaredFields(); Field[]fields=class1.getFields(); for(Fieldfield:declaredFields){ System.out.println("de--"+field); } for(Fieldfield:fields){ System.out.println("fields--"+field); } }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
de--privatejava.lang.Stringcom.app.Person.id de--privatejava.lang.Stringcom.app.Person.name de--publicjava.lang.Stringcom.app.Person.age fields--publicjava.lang.Stringcom.app.Person.age
实战1:通过反射,获取对象实例,并且操作对象的方法
packagecom.app; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person");; //创建实例化:相当于new了一个对象 Objectobject=class1.newInstance(); //向下转型 Personperson=(Person)object; person.setId("100"); person.setName("jack"); System.out.println("id:"+person.getId()+"name:"+person.getName()); }catch(ClassNotFoundExceptione){ e.printStackTrace(); }catch(InstantiationExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); } } }
运行结果:
id:100name:jack
实战2:通过反射获取对象字段属性,并且赋值
packagecom.app; importjava.lang.reflect.Field; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //创建实例 Objectperson=class1.newInstance(); //获得id属性 FieldidField=class1.getDeclaredField("id"); //给id属性赋值 idField.set(person,"100"); //打印person的属性值 System.out.println(idField.get(person)); }catch(InstantiationExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); }catch(NoSuchFieldExceptione){ e.printStackTrace(); }catch(SecurityExceptione){ e.printStackTrace(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
java.lang.IllegalAccessException:Classcom.app.T1cannotaccessamemberofclasscom.app.Personwithmodifiers"private" atsun.reflect.Reflection.ensureMemberAccess(UnknownSource) atjava.lang.reflect.AccessibleObject.slowCheckMemberAccess(UnknownSource) atjava.lang.reflect.AccessibleObject.checkAccess(UnknownSource) atjava.lang.reflect.Field.set(UnknownSource) atcom.app.T1.main(T1.java:20)
程序崩溃,原因是:id这个属性的是private私有的,不能修改它的值。
改进:
添加idField.setAccessible(true);
完整的代码为:
packagecom.app; importjava.lang.reflect.Field; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //创建实例 Objectperson=class1.newInstance(); //获得id属性 FieldidField=class1.getDeclaredField("id"); //打破封装实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的 idField.setAccessible(true); //给id属性赋值 idField.set(person,"100"); //打印person的属性值 System.out.println(idField.get(person)); }catch(InstantiationExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); }catch(NoSuchFieldExceptione){ e.printStackTrace(); }catch(SecurityExceptione){ e.printStackTrace(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
100
实战3:综合训练,反射操作属性和方法
packagecom.app; importjava.lang.reflect.Field; importjava.lang.reflect.InvocationTargetException; importjava.lang.reflect.Method; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //创建实例 Objectperson=class1.newInstance(); //获得id属性 FieldidField=class1.getDeclaredField("id"); //打破封装实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的 idField.setAccessible(true); //给id属性赋值 idField.set(person,"100"); //获取setName()方法 MethodsetName=class1.getDeclaredMethod("setName",String.class); //打破封装 setName.setAccessible(true); //调用setName方法。 setName.invoke(person,"jack"); //获取name字段 FieldnameField=class1.getDeclaredField("name"); //打破封装 nameField.setAccessible(true); //打印person的id属性值 Stringid_=(String)idField.get(person); System.out.println("id:"+id_); //打印person的name属性值 Stringname_=(String)nameField.get(person); System.out.println("name:"+name_); //获取getName方法 MethodgetName=class1.getDeclaredMethod("getName"); //打破封装 getName.setAccessible(true); //执行getName方法,并且接收返回值 Stringname_2=(String)getName.invoke(person); System.out.println("name2:"+name_2); }catch(IllegalArgumentExceptione){ e.printStackTrace(); }catch(InvocationTargetExceptione){ e.printStackTrace(); }catch(NoSuchMethodExceptione){ e.printStackTrace(); }catch(InstantiationExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); }catch(NoSuchFieldExceptione){ e.printStackTrace(); }catch(SecurityExceptione){ e.printStackTrace(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
id:100 name:jack name2:jack
实战4:静态属性、静态方法调用
定义Util类
packagecom.app; publicclassUtil{ publicstaticStringname="json"; /** *没有返回值,没有参数 */ publicstaticvoidgetTips(){ System.out.println("执行了---------1111"); } /** *有返回值,没有参数 */ publicstaticStringgetTip(){ System.out.println("执行了---------2222"); return"tip2"; } /** *没有返回值,有参数 *@paramname */ publicstaticvoidgetTip(Stringname){ System.out.println("执行了---------3333参数:"+name); } /** *有返回值,有参数 *@paramid *@return */ publicstaticStringgetTip(intid){ System.out.println("执行了---------4444参数:"+id); if(id==0){ return"tip1444--1"; }else{ return"tip1444--2"; } } }
完整小例子:
packagecom.app; importjava.lang.reflect.Field; importjava.lang.reflect.InvocationTargetException; importjava.lang.reflect.Method; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Util"); //获取nameField属性 FieldnameField=class1.getDeclaredField("name"); //获取nameField的值 Stringname_=(String)nameField.get(nameField); //输出值 System.out.println(name_); //没有返回值,没有参数 MethodgetTipMethod1=class1.getDeclaredMethod("getTips"); getTipMethod1.invoke(null); //有返回值,没有参数 MethodgetTipMethod2=class1.getDeclaredMethod("getTip"); Stringresult_2=(String)getTipMethod2.invoke(null); System.out.println("返回值:"+result_2); //没有返回值,有参数 MethodgetTipMethod3=class1.getDeclaredMethod("getTip",String.class); Stringresult_3=(String)getTipMethod3.invoke(null,"第三个方法"); System.out.println("返回值:"+result_3); //有返回值,有参数 MethodgetTipMethod4=class1.getDeclaredMethod("getTip",int.class); Stringresult_4=(String)getTipMethod4.invoke(null,1); System.out.println("返回值:"+result_4); }catch(InvocationTargetExceptione){ e.printStackTrace(); }catch(IllegalArgumentExceptione){ e.printStackTrace(); }catch(NoSuchMethodExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); }catch(NoSuchFieldExceptione){ e.printStackTrace(); }catch(SecurityExceptione){ e.printStackTrace(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果:
json 执行了---------1111 执行了---------2222 返回值:tip2 执行了---------3333参数:第三个方法 返回值:null 执行了---------4444参数:1 返回值:tip1444--2
当参数是int类型和Integer类型,反射获取方法不一样
①当参数是int类型时
/** *没有返回值,有参数 *@paramid */ publicstaticvoidgetTip(intid){ }
获取方法的时候需要用:int.class。不能使用Integer.class.会报错。
MethodgetTipMethod4=class.getDeclaredMethod("getTip",int.class); Stringresult_4=(String)getTipMethod4.invoke(null,1); System.out.println("返回值:"+result_4);
②当参数是Integer类型时
/** *没有返回值,有参数 *@paramid */ publicstaticvoidgetTip(Integerid){ }
获取方法的时候需要用:Integer.class。不能使用int.class.会报错。
MethodgetTipMethod4=class.getDeclaredMethod("getTip",Integer.class); Stringresult_4=(String)getTipMethod4.invoke(null,1); System.out.println("返回值:"+result_4);
创建对象实例
Person类
packagecom.app; publicclassPerson{ privateStringid; privateStringname; //构造函数1 publicPerson(){ System.out.println("构造函数无参"); } //构造函数2 publicPerson(Stringid){ this.id=id; System.out.println("构造函数id:"+id); } //构造函数3 publicPerson(Stringid,Stringname){ this.id=id; this.name=name; System.out.println("构造函数id:"+id+"name:"+name); } publicStringgetId(){ returnid; } publicvoidsetId(Stringid){ this.id=id; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } }
创建实例实战
packagecom.app; importjava.lang.reflect.Constructor; importjava.lang.reflect.InvocationTargetException; publicclassT1{ publicstaticvoidmain(String[]args){ try{ //创建类 Class>class1=Class.forName("com.app.Person"); //无参构造函数 Objectobject=class1.newInstance(); //有参构造函数:一个参数 Constructor>constructor=class1.getDeclaredConstructor(String.class); constructor.newInstance("1000"); //有参构造函数:二个参数 Constructor>constructor2=class1.getDeclaredConstructor(String.class,String.class); constructor2.newInstance("1001","jack"); }catch(InstantiationExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); }catch(InvocationTargetExceptione){ e.printStackTrace(); }catch(IllegalArgumentExceptione){ e.printStackTrace(); }catch(NoSuchMethodExceptione){ e.printStackTrace(); }catch(SecurityExceptione){ e.printStackTrace(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } }
运行结果
构造函数无参 构造函数id:1000 构造函数id:1001name:jack
总结
Class类提供了四个public方法,用于获取某个类的构造方法。
ConstructorgetConstructor(Class[]params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
ConstructorgetConstructors() 返回所有具有public属性的构造函数数组
ConstructorgetDeclaredConstructor(Class[]params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
ConstructorgetDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
四种获取成员方法的方法
MethodgetMethod(Stringname,Class[]params) 根据方法名和参数,返回一个具体的具有public属性的方法
Method[]getMethods() 返回所有具有public属性的方法数组
MethodgetDeclaredMethod(Stringname,Class[]params) 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
Method[]getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
四种获取成员属性的方法
FieldgetField(Stringname) 根据变量名,返回一个具体的具有public属性的成员变量
Field[]getFields() 返回具有public属性的成员变量的数组
FieldgetDeclaredField(Stringname) 根据变量名,返回一个成员变量(不分public和非public属性)
Field[]getDelcaredField() 返回所有成员变量组成的数组(不分public和非public属性)
更多关于java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。