---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
反射就 是把java类中的各种成分映射成相应的java类
Constructor
Method
Field
Package等等这些类代表的是字节码文件中的构造函数,字段,方法,包
用反射获取构造方法
Constructor constructor=String.class.getConstructor(StringBuffer.class);
用构造方法获取实例化对象
String str=(String)constructor.newInstance(new StringBuffer("aaaa"));
用Class中的newInstance获取实例化对象
String str1=String.class.newInstance();
Field
private static void changeStringValue(Object obj)throws Exception {
// TODO Auto-generated method stub
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
//在这里用==比较确切,因为字节码文件在内存中只存在一份,所以用==比equals方法更合适
if(field.getType() ==String.class){
String oldValue=(String)field.get(obj);
String newValue=oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
专家模式
谁拥有数据谁就是操作这个数据的专家
Method
Method methodCharAt=String.class.getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str, 2));
invoke方法的第一人参数是对象,如果为null那么这个Method对象对应的是一个静态方法
jdk1.4和jdk1.5中invoke方法的区别
在方法中如果有参数是数组,1.5中是可变参数,1.4中是数组
在传入的参数是数组时
在1.5中是Object类型的可变参数,而在1.4中是Object类型的数组
如 public static void main(String[] args),要接收的是一个String类型的数组
而public static void main(String... args),要接收的是n个String类型的对象
所以为了兼容1.4
我们在写程序的时候传入参数时,应该传一个数组
而在1.5中编译器会将数组打开以可变参数的形式接收这个数组。
所以在传入一个数组后,编译器会将数组打开,把打开后的每一个元素分别作为一个参数进行操作
这样在1.4中就会出现问题
因为将数组打开后的元素,就不再是这个方法要的参数,程序就会出错
那么我们可以将要传入的数组再封装到一个Object数组中,即mainMethod.invoke(null, new Object[]{new String[]{"111","222","3333"}});
这样在打开这个数组之后,还是一个数组,就可以按照我们的思想把数组传递进去
或者将其转换成Objcet类型的数组,即mainMethod.invoke(null, (Object)new String[]{"111","222","3333"});
这样是把String数组对象转换成了一个Object对象,就是告诉编译器,我传入的是一个对象不是一个数组,不需要打开
数组的反射
int[] a1=new int[]{1,2,3,4};
int[] a2=new int[3];
int[][] a3=new int[2][3];
String[] a4=new String[]{"a","b","c"};
System.out.println(a1.getClass()==a2.getClass());
//System.out.println(a1.getClass()==a3.getClass());
//System.out.println(a1.getClass()==a4.getClass());
System.out.println(a1.getClass().getName());
System.out.println(a3.getClass().getName());
System.out.println(a4.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a3.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
Object aobj1=a1;
Object aobj2=a3;
Object aobj3=a4;
//Object[] aobj4=a1;//基本数据类型不是Object类
Object[] aobj5=a3;
Object[] aobj6=a4;
System.out.println(Arrays.asList(a1,a4));
System.out.println(Arrays.asList(a1));
System.out.println(Arrays.asList(a4));
Array
是对数组进行反射的类
private static void printObject(Object obj) {
// TODO Auto-generated method stub
Class clazz=obj.getClass();
if (clazz.isArray()) {
int len=Array.getLength(obj);
System.out.print("[");
for (int i = 0; i < len; i++) {
if(i<len-1)
System.out.print(Array.get(obj, i)+", ");
else
System.out.println(Array.get(obj, i)+"]");
}
} else {
System.out.println(obj);
}
}
反射的应用
一般在做框架的时候用
package cn.itcast.day1;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;
public class ReflectTest2 {
/**
* @param args
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
//InputStream ips=new FileInputStream("src/cn/itcast/day1/config.properties");
//只能读取配置文件
//InputStream ips=ReflectTest2.class.getClassLoader().getResourceAsStream("resourse/config.properties");
InputStream ips=ReflectTest2.class.getResourceAsStream("resourse/config.properties");
Properties props=new Properties();
props.load(ips);
ips.close();
String className=props.getProperty("className");
Collection collection=(Collection)Class.forName(className).newInstance();
ReflectPoint pt1=new ReflectPoint(3, 5);
ReflectPoint pt2=new ReflectPoint(3, 3);
ReflectPoint pt3=new ReflectPoint(3, 3);
collection.add(pt1);
collection.add(pt2);
collection.add(pt3);
System.out.println(collection.size());
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------