------- android培训、java培训、期待与您交流! ----------
/* * 对两个使用了泛型的集合操作,出现下面问题 */ public static void main(String[] args) throws Exception { //通过反射向Integer集合中添加String可以正常取出打印 ArrayList<Integer> arr1 = new ArrayList<Integer>(); arr1.getClass().getMethod("add", Object.class).invoke(arr1, "abc"); System.out.println(arr1.get(0)); //通过反射向String集合中添加Integer,在打印时却出现类型转换异常 //这是什么原因? ArrayList<String> arr2 = new ArrayList<String>(); arr2.getClass().getMethod("add", Object.class).invoke(arr2, 2); System.out.println(arr2.get(0)); }泛型信息在生成class文件时被擦除,通过反射就可以操作原来不允许的类型。表面看来是没有问题的。
但是我们却忽略了编译时根据泛型String会静态绑定println(String str)方法,但是在运行时却取出了Integer类型,自然会出现类型转换异常。
如果泛型不是String,编译时会调用println(Object obj)方法,运行时再根据obj的实际类型动态绑定调用相应的toString方法,动态绑定实际上是运行时绑定,在运行时根据参数类型决定调用合适的方法。但是当在编译期可以明确的,就会静态绑定某个方法。
//TestArguments.main(new String[]{"111","222","333"}); String startingClassName = args[0]; Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); // invoke(obj, obj...args)invoke方法在JDK1.5的参数变为可变参数 //下面是两种可行的解决方法,将数组包装数组的元素或者明确字符串数组参数是一个对象 //mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}}); mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
public static void main(String[] args) throws Exception{ Properties props = new Properties(); //使用相对路径后去配置文件,移植性不好 //InputStream ips = new FileInputStream("config.properties"); /*一个类加载器能加载.class文件,那它当然也能加载classpath环境下的其他文件, 注意:直接使用类加载器时,文件名不能以/打头。*/ //InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/javaenhance/config.properties"); //Class提供了一个便利方法,用加载当前类的那个类加载器去加载相同包目录下的文件 //InputStream ips = ReflectTest2.class.getResourceAsStream("config.properties"); //如果使用class类加载器加载文件时,文件名以/开头,表示绝对路径,从classpath下寻找文件 InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/javaenhance/config.properties"); props.load(ips); Ips.close(); String className = props.getProperty("className"); Class clazz = Class.forName(className); //已经知道配置文件使用的是Collection的子类,通过反射创建对象 Collection collection = (Collection)clazz.newInstance(); //Collection collection = new ArrayList(); ReflectPoint pt1 = new ReflectPoint(3,3); ReflectPoint pt2 = new ReflectPoint(5,5); ReflectPoint pt3 = new ReflectPoint(3,3); collection.add(pt1); collection.add(pt2); collection.add(pt3); collection.add(pt1); System.out.println(collection.size()); }
JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。
如果方法名为setId,中文意思即为设置id,
如果方法名为getId,中文意思即为获取id,
去掉前缀,剩余部分就是属性名。
public class IntroSpectorTest { /** * @param args */ public static void main(String[] args) throws Exception { // 创建一个JavaBean对象pt1 ReflectPoint pt1 = new ReflectPoint(3,5); String propertyName = "x"; //"x"-->"X"-->"getX"-->MethodGetX--> //抽取获取属性值的方法,通过内省返回pt1对象的propertyName属性的值 Object retVal = getProperty(pt1, propertyName); System.out.println(retVal); Object value = 7; //抽取设置属性值的方法,通过内省设置pt1对象的propertyName属性的值为value setProperties(pt1, propertyName, value); //BeanUtils工具包,BeanUtils类get属性返回String字符串 System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName()); //BeanUtils类set属性时可以接受任意类型的对象,通常使用字符串 BeanUtils.setProperty(pt1, "x", "9"); System.out.println(pt1.getX()); //java7的新特性,Map的初始化方式 // Map map = {name:"zxx",age:18}; // BeanUtils.setProperty(map, "name", "lhm"); //在JavaBean类ReflectPoint中定义一个Date字段,可以直接通过字段设置Date的time属性 BeanUtils.setProperty(pt1, "birthday.time", "111"); System.out.println(BeanUtils.getProperty(pt1, "birthday.time")); //PropertyUtils的get属性时返回的结果为该属性本来的类型,set属性时只接受该属性本来的类型 PropertyUtils.setProperty(pt1, "x", 9); System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName()); } private static void setProperties(Object pt1, String propertyName, Object value) throws Exception { PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodSetX = pd2.getWriteMethod(); methodSetX.invoke(pt1,value); } private static Object getProperty(Object pt1, String propertyName) throws Exception { //使用PropertyDescriptor获取属性的方法 /*PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodGetX = pd.getReadMethod(); Object retVal = methodGetX.invoke(pt1);*/ //BeanInfo接口,通过内省获取JavaBean的信息 BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass()); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); Object retVal = null; for(PropertyDescriptor pd : pds){ if(pd.getName().equals(propertyName)) { Method methodGetX = pd.getReadMethod(); retVal = methodGetX.invoke(pt1); break; } } return retVal; } }
------- android培训、java培训、期待与您交流! ----------