JAVA动态性之一一反射机制reflection
package com.bjsxt.reflection.test.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 User(int id, int age, String uname) { super(); this.id = id; this.age = age; this.uname = uname; } public User() { super(); // TODO Auto-generated constructor stub } }
package com.bjsxt.reflection.test; /** * * 测试各种类型(class,interface,enum,annotation,primitive type,void)java。lang。Class对象获取方式 * @author Administrator * */ @SuppressWarnings("all") public class Demo01 { public static void main(String[] args) { String path = "com.bjsxt.reflection.test.bean.User"; try { Class clazz = Class.forName(path); // 一个类被加载后 JVM就会创建一个该类的Class对象。类的结构信息会放大对应的Class对象中 System.out.println(clazz.hashCode()); Class clazz2 = Class.forName(path); System.out.println(clazz2.hashCode());//同一个类只有一个反射对象 Class strClazz = String.class; Class strClazz2 = path.getClass(); System.out.println(strClazz == strClazz2); Class intClazz = int.class; //数组 同样的数据类 比较是不是同一个维度 不同 则不同 int[]arr01 = new int[10]; int[]arr02 = new int[30]; //2维数组 int[][]arr03 = new int [3][3]; System.out.println(arr01.getClass().hashCode()); System.out.println(arr02.getClass().hashCode()); System.out.println(arr03.getClass().hashCode()); double[]arr04 = new double[10]; System.out.println(arr04.getClass().hashCode()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
1442002549 1442002549 true 1383884648 1383884648 1701381926 1381270477
以上是如何获取
各种类型(class,interface,enum,annotation,primitive type,void)java。lang。Class对象获取方式
获取到对象后,下面利用反射里面的Api
java.lang.reflect
做些事情
应用反射的API 获取类的信息(包的名字 类的名字 属性 方法 构造方法等)
package com.bjsxt.reflection.test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * 应用反射的API 获取类的信息(类的名字 属性 方法 构造方法等) * @author Administrator * */ public class Demo02 { public static void main(String[] args) { String path = "com.bjsxt.reflection.test.bean.User"; try { Class clazz = Class.forName(path); //获取包名+类名 System.out.println(clazz.getName()); // 获得类名 User System.out.println(clazz.getSimpleName()); //获取属性信息 //引入import java.lang.reflect.Field; Field[] fields = clazz.getFields();//返回所有属性 public的属性 如何是别的 获取不到 System.out.println(fields.length);//0 Field[] fields1 = clazz.getDeclaredFields();//获得所有的属性 不管你的访问修饰符是什么 System.out.println(fields.length);//3 for(Field temp:fields){ System.out.println("属性"+temp); } // Field f1 = clazz.getDeclaredField("id"); // Field f2 = clazz.getDeclaredField("age"); // Field f3 = clazz.getDeclaredField("uname"); //获得 方法信息 Method[] method = clazz.getDeclaredMethods(); Method m =clazz.getDeclaredMethod("getUname", null); Method m2 = clazz.getDeclaredMethod("setUname", String.class); //获得构造放方法的信息 Constructor[]constructors = clazz.getDeclaredConstructors();// 获得所有构造器 Constructor c= clazz.getDeclaredConstructor(null);// 获得无参构造器 Constructor c1= clazz.getDeclaredConstructor(int.class,int.class,String.class); //获得参数列表类型是int int String 方法的构造器 } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
动态调用 获取到的 类的信息 (属性 方法 构造器)
package com.bjsxt.reflection.test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import com.bjsxt.reflection.test.bean.User; public class Demo03 { public static void main(String[] args) { String path = "com.bjsxt.reflection.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,"王二"); System.out.println(u2.getUname()); //通过反射api调用普通方法 User u3 = clazz.newInstance(); Method method =clazz.getDeclaredMethod("setUname", String.class); method.invoke(u3, "张三");//25 26 行代码 相等于 u3.setUname("张三"); System.out.println(u3.getUname()); // 通过反射api调用属性 User u4 = clazz.newInstance(); Field f = clazz.getDeclaredField("uname"); f.setAccessible(true);//这个属性不用做安全检查了 可以直接访问 否则会报错 说不能访问私有属性 f.set(u4, "李四");//通过反射直接写属性的值 System.out.println(u4.getUname());//通过反射直接读属性的值 System.out.println(f.get(u4));//通过反射读属性 } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
反射机制的性能问题
使用setAccessible提高性能(setAccessible是启用/禁用访问安全的开关)
f.setAccessible(true);// 禁用安全检查 这个属性不用做安全检查了 可以直接访问 否则会报错 说不能访问私有属性
效率提高4倍
反射操作注解(annotation)
反正操作泛型(Generic)
java采用泛型擦除的机制来引入泛型,也就是说,泛型仅仅是给编译器javac看的,来确保数据的安全性和免去数据类型转换,但是,一旦编译完成,所有和泛型相关的东西都被擦除,这一点也可以从类编译的class文件反编译看到。
为了用反射操作泛型
Java就新增了几种类型来代表不能被归一到Class类中的类型,但又和基本数据类型齐名的类型,通常使用的是前两个:
- ParameterizedType:表示一种参数化的类型,比如Collection< String >
- GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
- TypeVariable:是各种类型变量的公共父接口
-
WildcardType:代表一种通配符类型表达式,比如?、? extends Number、? super Integer。(wildcard是一个单词:就是”通配符“)
package com.bjsxt.reflection.test; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import com.bjsxt.reflection.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 { //Demo04.class获得Demo04这个类的一个对象 //Demo04.class.getMethod("test01",Map.class,List.class);获得这个类的test01方法Method m这个对象 Method m = Demo04.class.getMethod("test01",Map.class,List.class); // m.getGenericParameterTypes();获得带泛型参数类型 Type[]t = m.getGenericParameterTypes(); for(Type paramType:t){ System.out.println("#"+paramType); //判断是否参数类型是带有泛型 if(paramType instanceof ParameterizedType ){ //强制转换成带泛型的参数类型((ParameterizedType) paramType) //.getActualTypeArguments();获得真正的带泛型参数类型 Type[]gernericTypes=((ParameterizedType) paramType).getActualTypeArguments(); for(Type genericType:gernericTypes){ System.out.println("泛型类型"+genericType); } } } } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
#java.util.Map<java.lang.String, com.bjsxt.reflection.test.bean.User> 泛型类型class java.lang.String 泛型类型class com.bjsxt.reflection.test.bean.User #java.util.List<com.bjsxt.reflection.test.bean.User> 泛型类型class com.bjsxt.reflection.test.bean.User
posted on 2017-10-16 18:55 PoeticalJustice 阅读(209) 评论(0) 编辑 收藏 举报