反射(Reflection):加载类,并解剖出类的各个组成部分(反射就是解剖的意思)
加载类,获得类的字节码(三种方式):
Class clazz1 = Class.forName("cn.xxx.bean.Person");
Class clazz2 = new Person().getClass();
Class clazz3 = Person().class;
解剖出类中的各个组成部分:
获得公共构造方法、公共方法、和公共属性:
public Constructor getConstructor(Class<?> ...ParameterTypes)
public Method getMethod(String name, Class<?> ...parameterTypes)
public Field getField(String name) //或getFields获取所有属性
获得所有的构造方法、公共方法、和公共属性:
public Constructor getDeclaredConstructor(Class<?>...ParameterTypes)
public Method getDeclaredMethod(String name, Class<?>...parameterTypes)
public Field getDeclaredField(String name)
反射一个类的构造方法,创建该类的对象:
反射无参数构造方法:Constructor c = clazz1.getConstructor(null); Person p = (Person) c.newInstance(null);
反射参数为String的构造方法:Constructor c = clazz1.getConstructor(String.class); Person p = (Person) c.newInstance("name");
反射参数为(String, int)的构造方法:Constructor c = clazz1.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("name", 123);
反射参数为List的私有构造方法:Constructor c = clazz1.getDeclaredConstructor(List.class); c.setAccessible(true); Person p = (Person) c.newInstance(new ArrayList());
简化的方式(无参数的情况):Person p = (Person) clazz1.newInstance(); //要求Person类中有无参的构造方法
反射并调用一个类的方法:
反射一个无参数的方法 aa1(){}:Method m = clazz1.getMethod("aa1", null); m.invoke(p, null); //p为前面创建的对象
反射带参数的方法 aa1(String, int){}:Method m = clazz1.getMethod("aa1", String.class, int.class); m.invoke(p, "张三", 38);
反射带参数的方法 aa1(String, int[]){}:Method m = clazz1.getMethod("aa1", String.class, int[].class); m.invoke(p, "张三", new int[]{38, 39});
反射带参数的私有方法 aa1(InputString){}:Method m = clazz1.getDeclaredMethod("aa1", InputString.class); m.setAccessible(true); m.invoke(p, new FileInputStream("c:\\1.txt"));
反射带参数的静态方法 aa1(int){}:Method m = clazz1.getMethod("aa1", int.class); m.invoke(p, 23); //p可以用null代替
反射main(String[])方法:Method m = clazz1.getMethod("main", String[].class); m.invoke(null, (Object)new String[]{"aa","bb"}); //注:一定要强转为一个Object,不然JDK为了向下兼容会把String[]先拆成两个参数再invoke,导致Wrong Number of Arguments错误
反射一个类中的属性:
获得一个属性的类型:Field f = clazz1.getField("name"); Class t = f.getType(); if(type.equals(String.class)){};
反射String name并获得它的值:Field f = clazz1.getField("name"); String name =(String) f.get(p); //p为前面创建的对象
反射String name并对它赋值:Field f = clazz1.getField("name"); String name =(String) f.set(p, "xxxxxx");
反射private int num:Field f = clazz1.getDeclaredField("num"); f.setAccessible(true); int num =(int) f.get(p);
反射private static int age:Field f = clazz1.getDeclaredField("age"); f.setAccessible(true); int age=(int) f.get(p);
内省(Introspector):用于方便地反射和操作Java Bean的属性
内省工具类:Introspector(java.beans.*包中)
[java] view plain copy
//获取Bean信息:
BeanInfo info = Introspector.getBeanInfo(Person.class);
//注:如果不想获取所继承的属性,则用getBeanInfo(Person.class, stopClass.class); stopClass是某一个祖先类,这个例子表示只获得stopClass的子孙直到Person的属性,不包括stopClass。
获得Bean的所有属性:
[java] view plain copy
PropertyDescriptor[] pds = info.getPropertyDescriptors();
for (PropertyDescriptor pd : pds){
System.out.println(pd.getName()); //获得属性的名称。注:只要有getter就算是一个属性,不一定要真正定义属性。实际上是获取getter中去掉“get”后把第一个字母变小写的字符串。
}
获取Bean的一个属性:
[java] view plain copy
PropertyDescriptor pd = new PropertyDescriptor("age", Person.class); //获得age属性
Method setter = pd.getWriteMethod(); //获得setter
setter.invoke(p, 45); //p为之前获得的一个Person实例
Method getter = pd.getReadMethod(); //获得getter
System.out.println(getter.invoke(p, null));
获取一个属性的类型
[java] view plain copy
System.out.println(pd.getPropertyType());
使用beanUtils(Apache开源项目)操纵java bean的属性:
需要使用第三方的包:commons-logging.jar, commons-beanutils-x.x.x.jar
[java] view plain copy
//为属性name赋值:
BeanUtils.setProperty(p, "name", "Jack"); //p为一个Person实例
//自动类型转换:
BeanUtils.setProperty(p, "age", "123"); //如果age属性是int,BeanUtils会自动把字符串“123”转换为int类型
//注:BeanUtils缺省只支持把String转成8种基本数据类型。
//给BeanUtils注册类型转换器:
ConvertUtils.register(new Converter(){ //注册一个日期转换器:String转Date
public Object convert(Class type, Object value){
if(value==null){
return null;
}
if(!(value instanceof String)){ //如果不是String类型
throw new ConversionException("只支持String类型的转换");
}
String str = (String) value;
if(str.trim().equals("")){
return null;
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(str); //字符串转Date
}catch(ParseException e){
throw new RuntimeException(e); //e要传送给JVM
}
}
}, Date.class);
BeanUtils.setProperty(p, "birthDate", "1980-01-02"); // birthDate为Person中Date类型的属性
注:BeanUtils jar包中已经定义好了一些实现了Converter接口的转换器,比如:
ConvertUtils.register(new DateLocaleConverter(), Date.class);
[java] view plain copy
//把map填充到bean中:
Map map = new HashMap();
map.put("name", "Jack");
map.put("birthdate", "1908-01-02");
...
ConvertUtils.register(new DateLocaleConverter(), Date.class);
Person p = new Persion();
BeanUtils.populate(p, map); //map 填入 p 中
转自Clement-Xu的csdn博客
顶
5