java的反射机制
2017-02-20 16:15
441 查看
什么是反射
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
套用别人的一句话说,反射就是将java类中的各种成分映射成相应的java类。
反射的作用
判断一个对象的类
取出类的modifiers,数据成员,方法,构造器,和超类.运行时构造类的实例
取得和设定对象数据成员的值。
在运行时刻调用动态对象的方法。
反射在框架里应用的很多,很多工具类底层也是反射机制实现的。如javaBean,自动调用get和set方法也是使用了反射/
反射的简单使用
下面是我最近复习反射机制的笔记
反射的包是java.lang.reflect。
下面是接下来测试需要用到的类:
反射获取包名和类名
(测试类的main方法调用我就省略了,以下同,代码有注释,我就不多写了)
运行结果:
com.Howard.test02.PointTest
三种获取获取class字节码文件的方式
运行结果:
获取父类以及实现的接口
运行结果:
获取构造方法以及利用构造方法实例化对象
运行结果:
获取成员变量
运行结果:
获取类的方法method
运行结果:
获取main方法并执行
这里我另创建一个类,含有main方法。
下面的方法就是用于通过反射获取上面类的方法并进行相关操作
运行结果:
数组的反射以及数组与Object的关系
运行结果:
反射的简单应用
1、将字符串中所有的b改为z
运行结果:
2、反射判断是否为数组,如果是 输出数组各个值
这里有必要说下我main调用传的参数:
运行结果:
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
套用别人的一句话说,反射就是将java类中的各种成分映射成相应的java类。
反射的作用
判断一个对象的类
取出类的modifiers,数据成员,方法,构造器,和超类.运行时构造类的实例
取得和设定对象数据成员的值。
在运行时刻调用动态对象的方法。
反射在框架里应用的很多,很多工具类底层也是反射机制实现的。如javaBean,自动调用get和set方法也是使用了反射/
反射的简单使用
下面是我最近复习反射机制的笔记
反射的包是java.lang.reflect。
下面是接下来测试需要用到的类:
package com.Howard.test02; import java.io.Serializable; /** * 用于java反射的测试类 * @author Howard * 2017年2月17日 */ public class PointTest implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private int x; public int y; public String str_1 = "alibaba"; public String str_2 = "basketball"; public String str_3 = "tomorrow"; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public PointTest(int x, int y) { super(); this.x = x; this.y = y; } public PointTest() { super(); } @Override public String toString() { return "PointTest [x=" + x + ", y=" + y + ", str_1=" + str_1 + ", str_2=" + str_2 + ", str_3=" + str_3 + "]"; } }
反射获取包名和类名
(测试类的main方法调用我就省略了,以下同,代码有注释,我就不多写了)
/** * 获取类名以及包名 */ public static void getNameAndPackage(){ System.out.println(PointTest.class.getName()); //com.Howard.test02.PointTest }
运行结果:
com.Howard.test02.PointTest
三种获取获取class字节码文件的方式
/** * 三种获取class字节码的方式 * 相关比较 * @throws ClassNotFoundException */ public static void getClazz() throws ClassNotFoundException{ Class<?> clazz_1 = PointTest.class; Class<?> clazz_2 = new PointTest().getClass(); //抛ClassNotFoundException异常 Class<?> clazz_3 = Class.forName("com.Howard.test02.PointTest"); System.out.println(clazz_1.getName()); System.out.println(clazz_2.getName()); System.out.println(clazz_3.getName()); //比较 System.out.println(clazz_1 == clazz_2); System.out.println(clazz_2 == clazz_3); String s = "abc"; //isPrimitive()是否为基本类型 System.out.println("string是否为基本类型:"+s.getClass().isPrimitive()); System.out.println(int.class == Integer.class); System.out.println(int.class == Integer.TYPE); System.out.println("int是否为基本类型:"+int.class.isPrimitive()); System.out.println("int[]是否为基本类型:"+int[].class.isPrimitive()); System.out.println("int[]是否为数组:"+int[].class.isArray()); }
运行结果:
获取父类以及实现的接口
/** * 获取父类以及接口 * @throws Exception */ public static void getSuperClass() throws Exception{ Class<?> clazz = Class.forName("com.Howard.test02.PointTest"); //获取父类 Class<?> superclass = clazz.getSuperclass(); Class<?>[] interfaces = clazz.getInterfaces(); System.out.println("父类:"+superclass.getName()); System.out.println("实现的接口:"); for(int i = 0;i<interfaces.length;i++){ System.out.println(interfaces[i]+" "); } /* 父类:java.lang.Object 实现的接口: interface java.io.Serializable */ }
运行结果:
获取构造方法以及利用构造方法实例化对象
/** * 获取构造方法并通过构造方法new出实例对象 * @throws Exception */ public static void getConstructor() throws Exception{ //String str = new String("abc"); //传入参数类型 Constructor<String> constructor_1 = String.class.getConstructor(StringBuffer.class); //通过构造器来实例化对象 //如果上面得到的Constructor没有明确泛型,下面就必须强制转换 //参数必须明确new出类型 直接用字符串是会报argument type mismatch异常 String str = constructor_1.newInstance(new StringBuffer("abc")); System.out.println(str.charAt(2)); }
运行结果:
获取成员变量
/** * 获取成员变量Field * 注意private的获取方式 * @throws Exception */ public static void getField() throws Exception{ PointTest poit = new PointTest(5, 7); Field fieldY = poit.getClass().getField("y"); //这时得到的fieldY只是一个变量 并不能说它的值为5 System.out.println(fieldY); System.out.println(fieldY.getType()); //得到值必须指定哪个具体对象 System.out.println(fieldY.get(poit)); System.out.println(fieldY.getInt(poit)); //使用下面的方法获取private的变量x,会认为看不到这个变量 在获取具体信息时会报java.lang.NoSuchFieldException: x // Field fieldX = poit.getClass().getField("x"); Field fieldX = poit.getClass().getDeclaredField("x"); //获取权限修饰符 int a = fieldX.getModifiers(); System.out.println(Modifier.toString(a)); //使用getDeclaredField获取x后,在获取值时仍会报xxx with modifiers "private" //private 无访问权限 所以通过下面的方法先强制访问 fieldX.setAccessible(true); System.out.println(fieldX.getType()); System.out.println(fieldX.get(poit)); }
运行结果:
获取类的方法method
/** * 获取方法method并执行 * @throws Exception */ public static void getMethod() throws Exception{ //反射实现如下语句 // String str = "abc"; // str.charAt(2); String str = "abc"; //第一个参数 方法名 第2~n个参数 参数类型 Method methodCharAt = String.class.getMethod("charAt", int.class); System.out.println(methodCharAt.invoke(str, 2)); System.out.println(methodCharAt.invoke(str, new Object[]{2})); }
运行结果:
获取main方法并执行
这里我另创建一个类,含有main方法。
package com.Howard.test02; /** * 用于反射测试主函数 * @author Howard * 2017年2月17日 */ public class ArgumentsTest { public static void main(String[] args) { System.out.println("test!!!!"); if(args.length>0){ System.out.println(args[0]); } } }
下面的方法就是用于通过反射获取上面类的方法并进行相关操作
/** * 获取com.Howard.test02.ArgumentsTest的main方法并传参数执行 * @throws Exception */ public static void TestMain() throws Exception{ ArgumentsTest.main(new String[]{}); System.out.println(ArgumentsTest.class.getName()); Method method = ArgumentsTest.class.getMethod("main", String[].class); //下面的参数这样写会报错java.lang.NoSuchMethodException //因为jdk会自动拆箱为多个参数,但是该方法只要一个数组参数 //method.invoke(null, new String[]{"123","234"}); //下面这样写会把参数包成一个数组 method.invoke(null, new Object[]{new String[]{"123","234"}}); method.invoke(null, (Object)new String[]{"123","234"}); }
运行结果:
数组的反射以及数组与Object的关系
/** * 数组与Object的关系以及数组的反射 */ public static void testArray(){ int[] a1 = new int[]{1,2,3,}; int[] a2 = new int[4]; int[][] a3 = new int[2][3]; String[] a4 = new String[]{"a","b","c","d"}; System.out.println(a1.getClass() == a2.getClass()); //下面三者无法比较 // System.out.println(a2.getClass() == a3.getClass()); // System.out.println(a3.getClass() == a4.getClass()); // System.out.println(a4.getClass() == a1.getClass()); //[I [表示数组 I表示int System.out.println(a1.getClass().getName()); System.out.println(a3.getClass().getName()); System.out.println(a1.getClass().getSuperclass().getName()); System.out.println(a2.getClass().getSuperclass().getName()); //引伸 Object aObj1 = a1; Object aObj2 = a4; Object aObj3 = a3; //下面这个编译就过不去 // Object[] aObj4 = a1; Object[] aObj5 = a3; Object[] aObj6 = a4; //下面的结果是: //[I@15db9742 //[Ljava.lang.String;@6d06d69c System.out.println(a1); System.out.println(a4); //如果想看到数组里面的具体值。使用arrays工具类: //结果: //[[I@15db9742] //[a, b, c, d] //asList接收的是T...a //根据上面Object测试结果int数组是被当作Object的,而string数组可以被当作Object数组的,所以会有下面的结果 System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(a4)); }
运行结果:
反射的简单应用
1、将字符串中所有的b改为z
/** * 练习 * 将PointTest中string类型的值中b改为z * @throws Exception */ public static void practiceChangeString() throws Exception{ PointTest poit = new PointTest(); System.out.println("old:"+poit); //获取所有成员变量 Field[] fields = poit.getClass().getDeclaredFields(); for(Field field:fields){ //字节码比较 用== if(field.getType() == String.class){ String oldvalue =(String)field.get(poit); String newvalue = oldvalue.replace("b", "z"); field.set(poit, newvalue); } } System.out.println("new:"+poit); }
运行结果:
2、反射判断是否为数组,如果是 输出数组各个值
/** * 数组反射 获取类并判断是否为数组 如果是 输出各个数 * @param obj */ public static void practiceArray(Object obj){ Class clazz = obj.getClass(); System.out.println(clazz.getName()); if(clazz.isArray()){ System.out.println(clazz.isArray()); int len = Array.getLength(obj); for(int i = 0;i<len;i++){ System.out.println(Array.get(obj, i)); } }else{ System.out.println(obj); } }
这里有必要说下我main调用传的参数:
practiceArray("abc"); practiceArray(new String[]{"1","2","3"});
运行结果:
相关文章推荐