1. 动态语言
程序运行时,可以改变结构或变量类型。典型的语言:
function test(){ var s = "var a=3;var b=5;alert(a+b);"; eval(s); }
2. 反射机制reflection
Class c = Class.forName(cn.stu.test.User);
例1:
1 public class Demo01 { 2 public static void main(String[] args) { 3 String path = "cn.stu.ref.bean.User"; 4 5 try { 6 //方法一 7 Class clazz = Class.forName(path); 8 // 9 /** 10 * ================================== 11 * 对象时表示或封装一些数据。一个类被加载后, 12 * JVM会创建一个对应该类的Class对象 13 * 类的整个结构信息会会放到对应的Class对象中。 14 * 这个Class对象就是一面镜子一样, 15 * 通过这面镜子我们可以看到对应类的全部信息 16 * =================================== 17 */ 18 System.out.println(clazz.hashCode()); 19 //一个类只对应一个Class对象 20 Class clazz2 = Class.forName(path); 21 System.out.println(clazz2.hashCode()); 22 23 //方法二 24 Class strClass = String.class; 25 Class strClass2 = path.getClass(); 26 System.out.println(strClass==strClass2); 27 28 } catch (ClassNotFoundException e) { 29 e.printStackTrace(); 30 } 31 } 32 }
3. Class类介绍
当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM便自动产生一个Class对象
Class类似Reflection的根源
针对任何你想动态加载、运行的类,唯有先获得相应的Class对象
Class类的对象如何获取?
例2:
1 public class Demo02 { 2 3 public static void main(String[] args) { 4 String path = "cn.stu.ref.bean.User"; 5 try { 6 Class clazz = Class.forName(path); 7 8 //获取类的名称 9 System.out.println(clazz.getName());//类名+包名 10 System.out.println(clazz.getSimpleName());//类名 11 12 //获取属性名 13 Field[] fields = clazz.getFields(); //只能获得public的属性 14 Field[] fields2 = clazz.getDeclaredFields();//获得所有属性 15 Field field = clazz.getDeclaredField("name");//获取指定name属性 16 17 //获取方法名称 18 Method[] method = clazz.getDeclaredMethods(); 19 Method m1 = clazz.getDeclaredMethod("getName", null); 20 //如果方法有参,则必须传递参数类型对应的class对象 21 Method m2 = clazz.getDeclaredMethod("setName", String.class); 22 23 //获取构造器 24 Constructor[] constructors = clazz.getDeclaredConstructors(); 25 Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class); 26 27 } catch (Exception e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 } 31 } 32 }
例3:
1 public class Demo03 { 2 public static void main(String[] args) { 3 String path = "cn.stu.ref.bean.User"; 4 5 try { 6 Class clazz = Class.forName(path); 7 8 //通过反射API调用构造方法,构造对象 9 User u = (User) clazz.newInstance();//其实是调用了User的无参构造方法 10 11 Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class); 12 User u2 = (User) c.newInstance(1001,18,"张三"); 13 14 //通过反射API调用普通方法 15 User u3 = (User) clazz.newInstance(); 16 Method method = clazz.getDeclaredMethod("setName", String.class); 17 method.invoke(u3,"李四"); //u3.setName("李四") 18 19 //通过反射API操作属性 20 User u4 = (User) clazz.newInstance(); 21 Field f = clazz.getDeclaredField("name"); 22 f.setAccessible(true);//不做安全检查,直接访问 23 f.set(u4, "二麻子"); //通过反射直接写属性 24 String name = u4.getName(); 25 String name2 = (String) f.get(u4); //通过反射直接读属性的值 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 }
4. 反射机制性能问题
例4:
1 /** 2 * 通过跳过安全检查,提高反射效率 3 * 三种执行方法的效率差异比较 4 */ 5 public class Demo04 { 6 7 public static void test01(){ 8 User u = new User(); 9 10 long startTime = System.currentTimeMillis(); 11 12 for (int i = 0; i < 1000000000L; i++) { 13 u.getName(); 14 } 15 16 long endTime = System.currentTimeMillis(); 17 System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms"); 18 } 19 20 public static void test02() throws Exception{ 21 User u = new User(); 22 Class clazz = u.getClass(); 23 Method m = clazz.getDeclaredMethod("getName", null); 24 // m.setAccessible(true); 25 26 long startTime = System.currentTimeMillis(); 27 28 for (int i = 0; i < 1000000000L; i++) { 29 m.invoke(u, null); 30 } 31 32 long endTime = System.currentTimeMillis(); 33 System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms"); 34 } 35 36 public static void test03() throws Exception{ 37 User u = new User(); 38 Class clazz = u.getClass(); 39 Method m = clazz.getDeclaredMethod("getName", null); 40 m.setAccessible(true); //不需要执行访问安全检查 41 42 long startTime = System.currentTimeMillis(); 43 44 for (int i = 0; i < 1000000000L; i++) { 45 m.invoke(u, null); 46 } 47 48 long endTime = System.currentTimeMillis(); 49 System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms"); 50 } 51 52 53 public static void main(String[] args) throws Exception { 54 test01(); 55 test02(); 56 test03(); 57 } 58 }
输出结果:
普通方法调用,执行10亿次,耗时:6665ms
反射动态方法调用,执行10亿次,耗时:62947ms
反射动态方法调用,跳过安全检查,执行10亿次,耗时:11864ms
5. 反射操作泛型
原文:http://www.cnblogs.com/dooor/p/5285572.html