1 动态语言:
1 Java语言动态性:
2 Java反射机制:
3 Java反射机制应用场景:
4 反射实例代码:
1 bean public class User { private int id; private int age; private String uname; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public void setUname() { this.uname = "zm"; } private void test(){ System.out.println("hadoop5"); } public User(int id, int age, String uname) { super(); this.id = id; this.age = age; this.uname = uname; } //javabean必须要有无参的构造方法! 以方便反射下 User u = clazz.newInstance(); public User() { } } 2 反射代码 public static void main(String[] args) { String path = "com.test.bean.User"; try { Class<User> clazz = (Class<User>) Class.forName(path); //通过反射API调用构造方法,构造对象 User u = clazz.newInstance(); //其实是调用了User的无参构造方法 System.out.println(u); Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class); User u2 = c.newInstance(1001,18,"zm二"); System.out.println(u2); System.out.println(u2.getUname()); // 通过反射创建实例对象后 可以直接调用对象里的Public方法 //通过反射API调用普通方法 User u3 = clazz.newInstance(); Method method = clazz.getDeclaredMethod("setUname", String.class);// 别人给我传什么方法名 我就调用这个方法 实现动态调用方法 method.invoke(u3, "zm三"); //u3.setUname("zm三"); System.out.println(u3.getUname()); // zm三 //通过反射API操作属性 User u4 = clazz.newInstance(); Field f = clazz.getDeclaredField("uname"); f.setAccessible(true); //这个属性不需要做安全检查了,可以直接访问 f.set(u4, "zm四"); //通过反射直接写属性 System.out.println(u4.getUname()); //通过反射直接读属性的值 System.out.println(f.get(u4)); } catch (Exception e) { e.printStackTrace(); } }
5 反射带来的效率下降问题:
反射机制下回导致性能低下, 如果必须使用反射,可以建议 将 setAccessible设置为true,
表示反射的对象在使用时取消Java语言访问检查,
通常,
不使用反射代码效率 = [20,30]*使用反射(setAccessible为false)
使用反射(setAccessible为false)效率 = 4*使用反射(setAccessible为true)
代码测试如下:
/** * 通过跳过安全检查,提高反射效率 * 三种执行方法的效率差异比较 * * 结果: * 普通方法调用,执行10亿次,耗时:4549ms 反射动态方法调用,执行10亿次,耗时:88568ms 反射动态方法调用,跳过安全检查,执行10亿次,耗时:22170ms * */ public class Demo06 { public static void test01(){ User u = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000L; i++) { u.getUname(); } long endTime = System.currentTimeMillis(); System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms"); } public static void test02() throws Exception{ User u = new User(); Class clazz = u.getClass(); Method m = clazz.getDeclaredMethod("getUname", null); // m.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000L; i++) { m.invoke(u, null); } long endTime = System.currentTimeMillis(); System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms"); } public static void test03() throws Exception{ User u = new User(); Class clazz = u.getClass(); Method m = clazz.getDeclaredMethod("getUname", null); m.setAccessible(true); //不需要执行访问安全检查 long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000L; i++) { m.invoke(u, null); } long endTime = System.currentTimeMillis(); System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms"); } public static void main(String[] args) throws Exception { test01(); test02(); test03(); } }
6 反射得到方法参数泛型类型和返回值泛型类型
/** * 通过反射获取泛型信息 * #java.util.Map<java.lang.String, com.bjsxt.test.bean.User> 泛型类型:class java.lang.String 泛型类型:class com.bjsxt.test.bean.User #java.util.List<com.bjsxt.test.bean.User> 泛型类型:class com.bjsxt.test.bean.User 返回值,泛型类型:class java.lang.Integer 返回值,泛型类型:class com.bjsxt.test.bean.User * */ public class Demo04 { public void test01(Map<String,User> map,List<User> list){ System.out.println("Demo04.test01()"); } public Map<Integer,User> test02(){ System.out.println("Demo04.test02()"); return null; } public static void main(String[] args) { try { //获得指定方法参数泛型信息 Method m = Demo04.class.getMethod("test01", Map.class,List.class); Type[] t = m.getGenericParameterTypes(); for (Type paramType : t) { System.out.println("#"+paramType); if(paramType instanceof ParameterizedType){ Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments(); for (Type genericType : genericTypes) { System.out.println("泛型类型:"+genericType); } } } //获得指定方法返回值泛型信息 Method m2 = Demo04.class.getMethod("test02", null); Type returnType = m2.getGenericReturnType(); if(returnType instanceof ParameterizedType){ Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments(); for (Type genericType : genericTypes) { System.out.println("返回值,泛型类型:"+genericType); } } } catch (Exception e) { e.printStackTrace(); } } }
7 反射操作注解 ----> 见 注解定义使用---orm映射注解使用简单介绍
8 反射main函数要注意的事:
Method m = c.getMethod("main",String[].class); m.invoke(null, (Object)new String[]{}); //由于可变参数是JDK5.0之后才有。 如果在反射main函数时不加上 (Object)强转成一个参数的话 会编译成:m.invoke(null,"aa","bb"),就发生了参数个数不匹配的问题。 //m.invoke(null, (Object)new String[]{}); OK //因此,必须要加上(Object)转型,避免这个问题。 //public static void main(String[] args)