JAVA学习之反射(1):Class类和java.lang.reflect包的使用

来源:互联网 发布:殷叶子演过的网络剧 编辑:程序博客网 时间:2024/06/02 13:31

一,能够分析类能力的程序称为“反射”,反射库(java.lang.reflect)提供了精心设计的工具集,以便编写能够动态操作Java代码的程序。

用一句经典的话概括反射:反射就是把java类中的各种成分映射成相应的java类。

二,在程序运行期间,java运行时系统始终为所有的对象维护一个类型标识。这个标识跟踪着每个对象所属的类。虚拟机利用该标识选择相应的方法执行。可以通过专门的Java类访问这些信息。保存这些信息的类被称为Class类。


如同一个Person对象表示一个特定的人一样,一个Class对象表示一个特定类的属性。

三,创建Class类对象有3中形式:

1,已知某对象,调用该对象的getClass()方法将返回一个Class类型的实例。

Person p;Class cc = p.getClass();
2,调用静态方法forName获得类名对应的Class对象。

String ss = "java.util.Date";Class cc = Class.forName(ss);
3,若T是任意的Java类型,T.class将代表匹配的类对象。

Class cc1 = java.util.Date.class;Class cc2 = int.class;Class cc3 = Double[].class
Class对象表示的是一个类型,而这个类型未必是一种类,如整型(int),数组(double[])


四,最常见的关于Class对象的两个操作

1,getName()方法获得类的名字

Person pp;syso(pp.getClass().getName()); //syso是System.out.println()的简写。
2,newInstance()方法快速创建一个类的实例

Person pp;Person pp2 = pp.getClass().newInstance();
pp和pp2是2个不同的对象,newInstance()方法调用默认构造器初始化新对象,若没有默认构造器,会抛出异常。


五,在java.lang.reflect包中有3个类Field,Method和Constructor分别用于描述类的域(成员变量),方法和构造器。

Class类中的getField(),getMethod(),getConstructor()方法分别返回类提供的公有域,公有方法和公有构造器。

Class类中的getDeclaredField(),getDeclaredMethod(),getDeclaredConstructor()方法分别返回类提供的私有域,私有方法和私有构造器。

下面是一个关于上述这几个类和方法使用的示例。

package com.jimmy.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;//创建一个类class Son2{//私有的成员变量private double i;//默认构造函数和有参构造函数public Son2() {}public Son2(double i) {this.i = i;}//成员变量的set和get方法public void setter(double i) {this.i = i;}public double getter() {return i;}}//测试Class类的函数和反射库中的函数public class test2 {public static void main(String[] args) throws Exception {//获得Son2类的Class对象。Class<?> cc = Son2.class;//先得到有参构造器的信息,再根据构造器的信息,由newInstance()函数创建一个Son2对象Constructor<?> constructor = cc.getConstructor(double.class);//要指定构造器参数的类型Son2 son = (Son2)constructor.newInstance(123);//newInstance()带上参数类型的实例。System.out.println(son.getter()); //输出被实例化对象son的成员变量的值:123.0。//先得到无参构造器的信息,再创建Son2对象Constructor<?> constructor1 = cc.getConstructor();Son2 son2 = (Son2)constructor1.newInstance();//Son2类中要有默认构造器System.out.println(son2.getter());//输出被实例化对象son2的成员变量的值:0.0。//由无参构造器创建对象时,可不必获得构造器,直接由Class对象调用newInstance()方法。Class<?> cc2 = Son2.class;Son2 son22 = (Son2)cc2.newInstance();System.out.println(son22.getter()); //输出被实例化对象son的成员变量的值:0.0//下面2个输出语句可看出cc保存类信息,输出的是“class + 类名”。cc.newInstance()是具体类的对象。System.out.println(cc);  //输出:class com.jimmy.reflect.Son2System.out.println(cc.newInstance());  //输出:com.jimmy.reflect.Son2@15db9742(对象的地址)//首先得到有参构造函数的信息,然后根据构造函数实例化一个对象。//由getDeclaredField()函数得到类里面的私有成员变量,访问私有成员变量要用setAccessible()函数设置访问权限。//Field类对象得到成员变量后还可以设置该变量的值,使用set()方法。Constructor<?> constructor2 = cc.getConstructor(double.class);Son2 son23 = (Son2)constructor2.newInstance(321);Field field = cc.getDeclaredField("i");field.setAccessible(true);field.set(son23, 213);System.out.println(field.get(son23));  //field.get(对象)返回获得的对应域的值。//首先根据获得的构造函数信息实例化一个对象//然后由函数名获得类中的公有函数,getMethod("函数名")//invoke()方法执行由getMethod()获得的函数,这里获得的函数是getter()//对于获得的无参函数,invoke(对象)里只添加对象名。Constructor<?> constructor3 = cc.getConstructor(double.class);Son2 son24 = (Son2)constructor3.newInstance(231);System.out.println(cc.getMethod("getter").invoke(son24)); //输出函数执行返回的结果//对于获得到的有参函数,在调用getMethod()函数时,要在getMethod()中指定被获得函数的"函数名"和"参数类型"//并且在执行该函数(即调用invoke()函数时),要指定对象和参数类型的具体实例。Son2 son25 = (Son2)cc.newInstance(); Method method = cc.getMethod("setter", double.class);method.invoke(son25, 123);System.out.println(son25.getter());  //输出函数执行返回的结果。//反射包里还有一个重要的类:Modifier,该类是静态类,其中的方法也都是静态方法//Class类中getModifiers()函数返回一个用于描述类,构造器,方法和域的修饰符的整形数值。、//调用Modifier.toString()方法将整型数值转变成字符串,也是就我们熟悉的public,private,static,final等修饰符。System.out.println(Modifier.toString(cc.getModifiers()));System.out.println(Modifier.toString(constructor.getModifiers()));System.out.println(Modifier.toString(field.getModifiers()));System.out.println(Modifier.toString(method.getModifiers()));//同时,Modifier类还有一些判断修饰符是不是某一类型的方法。System.out.println(Modifier.isPublic(cc.getModifiers()));System.out.println(Modifier.isPublic(constructor.getModifiers()));}}

六,应用反射调用其他类的main()方法

首先有一个类,main()方法输出信息:

package com.jimmy.reflect;public class testPrint {public static void main(String[] args) {for(String ss:args)System.out.println(ss);}}

在其他类中反射调用上面类的main()方法。

package com.jimmy.reflect;import java.lang.reflect.Method;public class getMain {public static void main(String[] args) throws Exception {//传统方法testPrint.main(new String[]{"haha","xixi"});//反射调用Class<?> cc = Class.forName("com.jimmy.reflect.testPrint");Method mm = cc.getMethod("main", String[].class);mm.invoke(null, (Object)new String[]{"hello","jimmy"});//实例化字符串数组对象时要在前面加(Object),不然会报参数个数不匹配的错误。}}

七,数组的反射

package com.jimmy.reflect;import java.lang.reflect.Array;public class test3 {public static void main(String[] args) throws Exception {//新建4个不同的数组int[] a = new int[3];int[] b = new int[4];int[][] c = new int[3][4];String[] d = new String[3];//可以对比各个数组所属的类是否相同System.out.println(a.getClass() == b.getClass());//System.out.println(a.getClass() == c.getClass()); //不同的类不能比较是否相等,会报错//System.out.println(a.getClass() == d.getClass());System.out.println(a.getClass().getName());System.out.println(d.getClass().getName());System.out.println(a.getClass().getSuperclass().getName());//利用静态方法反射生成一个数组int[] aa = (int[]) Array.newInstance(int.class, 3);Array.set(aa, 0, 123);//set()静态方法赋值Array.set(aa, 1, 321);Array.set(aa, 2, 213);System.out.println(Array.get(aa, 0));//get()静态方法取值System.out.println(Array.get(aa, 1));System.out.println(Array.get(aa, 2));//获得数组类型的常用方式Class<?> cc = String[].class;Class<?> cc1 = Class.forName("[I");Class<?> cc2 = Class.forName("[Ljava.lang.String;");System.out.println(cc);System.out.println(cc1);System.out.println(cc2);//通过已有对象获取数组类型Class<?> cc3 = aa.getClass();System.out.println(cc3);Class<?> cc4 = cc3.getComponentType();//根据类型信息获取数组内成员的类型System.out.println(cc4);}}





1 0
原创粉丝点击