反射
1,构造方法的反射
package javaBase.reflect; import java.lang.reflect.Constructor; /* * 三种获取字节码对应的实例对象(Class类型)的方法: * 九种预定义的 Class 对象,表示八个基本类型和 void * boolean、byte、char、short、int、long、float、 double。 * 源程序中出现的类型,都有各自的Class实例对象:int[] ,void ..... */ public class Test1 { public static void main(String[] args) throws Exception{ String str1 = "haha"; Class cls1 = str1.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String");//详细 System.out.println(cls1 == cls2);//true System.out.println(cls1 == cls3);//true //判断一个类是不是基本数据类型: System.out.println(cls1.isPrimitive());//false System.out.println(int.class.isPrimitive());//true System.out.println(int.class==Integer.class);//Integer是包装类,false System.out.println(int.class == Integer.TYPE);//type:包装的源数据类型 true System.out.println(int[].class.isPrimitive());//数组也是一个类型,不是原始类型 System.out.println(int[].class.isArray()); //Constructor类代表某个类中的一个构造方法 Constructor c1 = String.class.getConstructor(StringBuffer.class); // 用反射实现:String s1 = new String(new StringBuffer("abc")); String str2 = (String)c1.newInstance(new StringBuffer("abc")); //编译时:不会执行等号赋值,只检查语法,看定义,所以不知道c1是个什么对象的构造方法 System.out.println(str2.charAt(2)); } //反射就是将java类中的各种成分映射成相应的java类 }
2,成员变量的反射
package javaBase.reflect; //反射就是将java类中的各种成分映射成相应的java类 import java.lang.reflect.Constructor; import java.lang.reflect.Field; /* * 三种获取字节码对应的实例对象(Class类型)的方法: * 九种预定义的 Class 对象,表示八个基本类型和 void * boolean、byte、char、short、int、long、float、 double。 * 源程序中出现的类型,都有各自的Class实例对象:int[] ,void ..... */ public class Test1 { public static void main(String[] args) throws Exception{ String str1 = "haha"; Class cls1 = str1.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String");//详细 System.out.println(cls1 == cls2);//true System.out.println(cls1 == cls3);//true //判断一个类是不是基本数据类型: System.out.println(cls1.isPrimitive());//false System.out.println(int.class.isPrimitive());//true System.out.println(int.class==Integer.class);//Integer是包装类,false System.out.println(int.class == Integer.TYPE);//type:包装的源数据类型 true System.out.println(int[].class.isPrimitive());//数组也是一个类型,不是原始类型 System.out.println(int[].class.isArray()); //Constructor类代表某个类中的一个构造方法 Constructor c1 = String.class.getConstructor(StringBuffer.class); // 用反射实现:String s1 = new String(new StringBuffer("abc")); String str2 = (String)c1.newInstance(new StringBuffer("abc")); //编译时:不会执行等号赋值,只检查语法,看定义,所以不知道c1是个什么对象的构造方法 System.out.println(str2.charAt(2)); Point p = new Point(3, 5); //fieldY是类的,不是具体对象的。用它去取某个具体对象上对应的值 Field fieldY = p.getClass().getField("y");//y是类的字段名 System.out.println(fieldY.get(p)); // Field fieldX = p.getClass().getField("x");//找不到,x是private Field fieldX = p.getClass().getDeclaredField("x");//可以看见了,但是不能取 fieldX.setAccessible(true);//暴力反射 System.out.println(fieldX.get(p)); changeStringValue(p); System.out.println(p); } /* * 将一个对象中的String类型成员变量的值中“b”改成“a” */ private static void changeStringValue(Point p) throws Exception { Field[] fields = p.getClass().getFields(); for(Field f:fields){ if(f.getType()==String.class){//字节码只有一份,用==比较,而不用equals() String oldValue = (String)f.get(p);//获取成员变量值 String newValue = oldValue.replace("b", "a"); f.set(p, newValue);//成员变量重新赋值 } } } }
附:Point类
package javaBase.reflect; public class Point { private int x; public int y; public String str1 = "ball"; public String str2 = "bascketball"; public String str3 = "it"; public Point(int x, int y) { super(); this.x = x; this.y = y; } @Override public String toString() { return str1+": "+str2+": "+ str3; } }
3成员方法的反射
//Method 例子:charAt() Method mCharAt = String.class.getMethod("charAt", int.class); char ch = (Character)mCharAt.invoke(str1, 1);//invoke调用.str1这里为null是静态方法 System.out.println(ch);
4,main()方法反射
<span style="white-space:pre"> </span>new DoMain().main(new String[]{"111","222","333"}); //main()方法,不知道类的名字,只知道到时候传过来要调用其main方法 String someClassName = args[0];//传入类名(带包) Method mainMethod = Class.forName(someClassName).getMethod("main", String[].class); mainMethod.invoke(null, (Object)new String[]{"111","222","333"});//静态方法用null /* * jdk1.4把数组当成n个参数,jdk1.5把数组当做一个参数,为了兼容1.4: * java5会自动把数组弄成多个单独参数 * 这两种方法都可以避免数组被拆成几个参数 */ mainMethod.invoke(null, new Object []{new String[]{"111","222","333"}});
5,数组的反射
package javaBase.reflect; import java.lang.reflect.Array; /* * 数组的反射 */ public class ArrayReflect { public static void main(String[] args) { int[] a1 = new int[3]; int[] a2 = new int[4]; int[][] a3 = new int[2][3]; String[] s = new String[3]; System.out.println(int.class.getSuperclass());//null,基本类型没有父类? System.out.println(a1.getClass()==a2.getClass());//true维度,类型相同 // System.out.println(a1.getClass() == a3.getClass()); // System.out.println(a1.getClass() == s.getClass()); System.out.println(a1.getClass().getName());//类名:[I System.out.println(a1.getClass().getSuperclass().getName());//obj System.out.println(a3.getClass().getName());//[[I System.out.println(s.getClass().getSuperclass().getName());//obj Object o1 = a1; Object o2 = a3; Object o3 = s; // Object[] o4 = a1;//基本数据类型数组不是Object[];整个数组是一个Object对象 Object[] o5 = s; Object[] o6 = a3;//降低了维度 String[] strings = new String[]{"a","b","c"}; printObj(strings); printObj("haha"); } /* * 数组的反射类:Array */ private static void printObj(Object obj) { Class clazz = obj.getClass(); if(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); } } }
6,反射与框架,通过配置文件创建对象
package javaBase.reflect; import java.io.FileInputStream; import java.io.InputStream; import java.util.*; /* * 当一个对象存储到hashset中后,就不要修改那些参与计算哈希值的字段了 * 否则修改后的对象hashcode值与存入时不同,导致不能找到这个对象和单独删除该对象导致内存泄露 */ public class ReflectTest { public static void main(String[] args) throws Exception { InputStream in = new FileInputStream("config.properties"); Properties prop = new Properties(); prop.load(in); in.close();//关闭资源:当前操作系统的窗口或者什么为其提供资源的对象 //用反射建立集合 String className = prop.getProperty("className"); Collection c = (Collection)Class.forName(className).newInstance(); // Collection c = new HashSet(); Point p1 = new Point(3, 3); Point p2 = new Point(5, 5); Point p3 = new Point(3, 3); c.add(p1); c.add(p2); c.add(p3); c.add(p1); // p1.y = 7; c.remove(p1);//上面这句执行后会导致remove()找不到p1,从而不能删除 System.out.println(c.size()); } }