首页>>后端>>java->Java反射机制详解

Java反射机制详解

时间:2023-12-01 本站 点击:0

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。—百度百科

动态:运行期间动态绑定执行规则。

静态:编译以后就已经确定的执行过程。

一、动态获取类的信息

动态获取类的方法信息

Foo类(package:demo):

//编译以后是demo.Foo.class//类的全名是demo.FooclassFoo{publicinttest(){return5;}publicdoubletest1(){return5d;}}

动态获取Foo类的方法:

@TestpublicvoidtestClassForName(){/**动态的加载类信息到方法区*并且返回对应的Class对象!*Class对象可以访问类的全部信息!**将className对应的类文件,从磁盘中加载*内存方法区,返回这个类的信息*/StringclassName="demo.Foo";try{Class<?>cls=Class.forName(className);Method[]all=cls.getDeclaredMethods();for(Methodmethod:all){System.out.println(method.getName());}}catch(ClassNotFoundExceptione){e.printStackTrace();}}//输出://test//test1

动态获取类的属性信息

Eoo类:

classEoo{intid;Stringname;doublesalary;Stringmeno;publicEoo(){}publicEoo(intid,Stringname,doublesalary,Stringmeno){super();this.id=id;this.name=name;this.salary=salary;this.meno=meno;}//get,set略}

动态获取Eoo类的属性:

@TestpublicvoidtestField()throwsException{/**动态获取一个类的全部属性信息*1动态加载一个类到方法区*2动态获取类的属性信息*/StringclassName="demo.Eoo";//动态加载类Class<?>cls=Class.forName(className);//动态获取类声明的属性信息Field[]all=cls.getDeclaredFields();for(Fieldfield:all){//getName获取属性的名字System.out.print(field.getName()+"");}}//idnamesalarymeno

动态获取类的构造器信息

@TestpublicvoidtestCon()throwsException{/**1动态加载类*/StringclassName="demo.Eoo";Class<?>cls=Class.forName(className);Constructor[]all=cls.getDeclaredConstructors();for(Constructorc:all){System.out.print(c.getName());//获取构造器的参数类型列表//Parameter参数Type类型//Class[]代表所有参数的类型列表Class[]types=c.getParameterTypes();System.out.println(Arrays.toString(types));}}//demo.Eoo[]//demo.Eoo[int,classjava.lang.String,double,classjava.lang.String]

二、动态创建对象

调用无参构造器创建对象

如果没有无参数构造器,将发生异常!Class 提供了方法 newInstance()。

@TestpublicvoidtestNewInstance()throwsException{/**动态调用无参数构造器创建对象*1动态加载类*2利用class的方法newInstance执行*无参数构造器常见对象*注意:类必须有无参数,否则出异常*/StringclassName="java.util.Date";Class<?>cls=Class.forName(className);//cls.newInstance()调用无参数构造器创建对象Objectobj=cls.newInstance();System.out.println(obj);//静态的创建对象!编译已经就固定了!Datedate=newDate();}//FriSep1620:04:55CST2016

调用有参构造器创建对象

如果没有对应有参数构造器!将发生异常!参数传递错误、将发生异常!

/***调用className类名对应的类的有参数构造器,paramTypes代表对应构造器的参数列表*className+paramTypes共同决定调用哪个构造器!执行构造器还需要具体的参数params*/publicObjectcreate(StringclassName,Class[]paramTypes,Object[]params)throwsException{//动态加载类//动态获取指定参数类型的构造器//执行这个构造器,传递params参数。Class<?>cls=Class.forName(className);//getDeclaredConstructor在类信息中查找//给定参数类型的构造器信息Constructorc=cls.getDeclaredConstructor(paramTypes);//执行构造器c.newInstance()方法,创建对象//返回值就是这个构造器创建的对象Objectobj=c.newInstance(params);returnobj;}@TestpublicvoidtestCreate()throwsException{StringclassName="java.util.Date";//类型列表==Class类型的数组Class[]paramTypes={long.class};//实际参数列表Object[]params={-1000L*60*60*24*365};Objectobj=create(className,paramTypes,params);System.out.println(obj);//思考:如何动态调用newString("Hello");className="java.lang.String";/**{}只能拥有声明变量时候直接初始化*不能用于赋值语句!*赋值语句可以使用newObject[]{"Hello"}*/paramTypes=newClass[]{String.class};params=newObject[]{"Hello"};obj=create(className,paramTypes,params);System.out.println(obj);//Hello//思考:如何动态调用newString(byte[],"utf-8");obj=create("java.lang.String",newClass[]{byte[].class,String.class},newObject[]{newbyte[]{65,66,67,68},"UTF-8"});System.out.println(obj);}//WedJan0108:00:00CST1969//Hello//ABCD

三、动态获取类的属性值

实现过程(如何利用反射API实现动态属性访问):

1、找到对象的类型信息(方法区)

2、在信息中找属性信息(Field)

3、在对象上获取属性的值!

类Goo:

publicclassGoo{publicintid;publicStringname;publicGoo(){}publicGoo(intid,Stringname){super();this.id=id;this.name=name;}}

动态获取属性的值:

/***获取obj对象的fieldName对应属性的值*@paramobj*@paramfieldName*@return属性值*/publicObjectget(Objectobj,StringfieldName)throwsException{//1获取类信息/**Java中对象的getClass()方法可以获取对象的类型信息!*Java中有3种方法可以获取Class信息*1.类名.class获取类信息(静态)*2.Class.forName("类名")获取类信息动态*3.obj.getClass()获取类信息。运行期间,通过当前对象获取类信息*/Class<?>cls=obj.getClass();//找到属性:/**getDeclaredField按照属性名在cls中查找*类信息。当属性没有找到时候,抛出异常!*/Fieldfield=cls.getDeclaredField(fieldName);//在对象上获取属性的值!/**get方法:在一个对象上获取属性的值,对象上没有对应的属性,抛出异常*/Objectvalue=field.get(obj);returnvalue;}@TestpublicvoidtestGetField()throwsException{/**动态获取对象的属性*/Googoo=newGoo(5,"Tom");Objectv1=get(goo,"id");Objectv2=get(goo,"name");System.out.println(v1+""+v2);}//5Tom

四、动态调用类的方法

@Testpublicvoidtestinvoke()throwsException{List<String>list=newArrayList<String>();list.add("tom");list.add("jack");//动态获取类信息Class<?>cls=list.getClass();//通过方法名和参数类型找到对应的方法Methodmethod=cls.getDeclaredMethod("remove",newClass[]{int.class});//调用方法,传递对象和具体参数Objectvalue=method.invoke(list,newObject[]{0});System.out.println(value);//tom}

五、反射的意义

常见的框架的底层都是使用反射实现的!如:Spring、MyBatis、Struts2、Hibernate …

现有application.xml文件:

@TestpublicvoidtestClassForName(){/**动态的加载类信息到方法区*并且返回对应的Class对象!*Class对象可以访问类的全部信息!**将className对应的类文件,从磁盘中加载*内存方法区,返回这个类的信息*/StringclassName="demo.Foo";try{Class<?>cls=Class.forName(className);Method[]all=cls.getDeclaredMethods();for(Methodmethod:all){System.out.println(method.getName());}}catch(ClassNotFoundExceptione){e.printStackTrace();}}//输出://test//test10

模拟Spring框架的getBean()方法:

@TestpublicvoidtestClassForName(){/**动态的加载类信息到方法区*并且返回对应的Class对象!*Class对象可以访问类的全部信息!**将className对应的类文件,从磁盘中加载*内存方法区,返回这个类的信息*/StringclassName="demo.Foo";try{Class<?>cls=Class.forName(className);Method[]all=cls.getDeclaredMethods();for(Methodmethod:all){System.out.println(method.getName());}}catch(ClassNotFoundExceptione){e.printStackTrace();}}//输出://test//test11


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/5465.html