---------------------- 黑马程序员 Android培训、期待与您交流! ---------------------
反射: 通过class文件的对象,获取构造函数、字段、方法的操作
学习反射的目的:
有些时候,可能JDK中的方法没有在帮助文档中提供,但是通过查看源代码,却发现有这个方法,不会该方法为private
私有,所以JDK的帮助文档没有提供该方法
如果,必须要用这个方法, 我们可以通过反射的方式来获取,进行使用
构造函数: Constructor
字段:Field
方法:Method
如何获取Person类的 字节码文件对象呢?
方式1: getClass(): 返回进行时的类
方式2: 数据类型.class 静态属性,来获取当前数据类型的字节码文件对象
方式3: public static Class forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象
构造函数: Constructor
Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。
例如,使用它能获得 Java 类中各成员的名称并显示出来。
实例:
1.给类的字段赋值(通过Method, 而不是field.set)
public class ReflectDemo {public static void getobj1(Object obj, String[] fields, Object[] values) throws Exception {
Class cl = obj.getClass();
for (int i = 0; i < fields.length; i++) {
String str = "set";
Field fie = cl.getDeclaredField(fields[i]);
String methodname = str + fields[i].substring(0, 1).toUpperCase()
+ fields[i].substring(1);
System.out.println(methodname);
Class partype = fie.getType();
System.out.println(partype);
Method me = cl.getDeclaredMethod(methodname, partype);
me.invoke(obj, values[i]);
}
}
public static Object getobj(String classname, Map<String, Object>k_v ) throws Exception {
Class cl = Class.forName(classname);
Object o = cl.newInstance();
Iterator<String> it = k_v.keySet().iterator();
Pattern pattern = Pattern.compile("^\\w");
while (it.hasNext()) {
String pro = it.next();
// String
// ss="set"+pro.substring(0,1).toUpperCase()+pro.substring(1);
Matcher mat = pattern.matcher(pro);
String ss = "set";
if (mat.find()) {
ss += mat.replaceFirst(mat.group(0).toUpperCase());
}
cl.getMethod(ss, k_v.get(pro).getClass()).invoke(o, k_v.get(pro));
}
return o;
}
/* public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
// T_user t=new T_user();
// getobj(t, new String[]{"age","name"},new Object[]{10,"zs"});
// System.out.println(t.getName()+" "+t.getAge());
Map map = new HashMap();
map.put("id", 1);
map.put("name", "ss");
Timer t1 = (Timer) getobj("org.hzy.dao.T_user", map);
// System.out.println(t1.getId()+" "+t1.getAge()+" "+t1.getName());
}
public static void getobj(Object obj,String[] fields,Object[] values) throws Exception{
Class cl=obj.getClass();
for (int i = 0; i < fields.length; i++) {
String str="set";
Field fie=cl.getDeclaredField(fields[i]);
String methodname=str+fields[i].substring(0, 1).toUpperCase()+fields[i].substring(1);
System.out.println(methodname);
Class partype=fie.getType();
System.out.println(partype);
Method me=cl.getDeclaredMethod(methodname, partype);
me.invoke(obj, values[i]);
}
}
public static Object getobj1(String classname,Map<String, Object> k_v) throws Exception{
Class cl=Class.forName(classname);
Object o=cl.newInstance();
Iterator<String> it=k_v.keySet().iterator();
Pattern pattern=Pattern.compile("^\\w");
while (it.hasNext()) {
String pro=it.next();
// String ss="set"+pro.substring(0,1).toUpperCase()+pro.substring(1);
Matcher mat=pattern.matcher(pro);
String ss="set";
if(mat.find()){
ss+=mat.replaceFirst(mat.group(0).toUpperCase());
}
cl.getMethod(ss, k_v.get(pro).getClass()).invoke(o, k_v.get(pro));
}
return o;
}
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
// T_user t=new T_user();
// getobj(t, new String[]{"age","name"},new Object[]{10,"zs"});
// System.out.println(t.getName()+" "+t.getAge());
Map map=new HashMap();
map.put("id",1);
map.put("name", "ss");
Timer t1=(Timer)getobj("org.hzy.dao.T_user", map);
//System.out.println(t1.getId()+" "+t1.getAge()+" "+t1.getName());
}
//得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。
}
}ss
2. 得到某个对象的属性package HighMoney;
public class ReflectDemo {
public Object getProperty1(Object owner, String fieldName) throws Exception {
Class ownerClass = owner.getClass();
Field field = ownerClass.getField(fieldName);
Object property = field.get(owner);
return property;
}
public Object getProperty(Object owner, String fieldName) throws Exception {
Class ownerClass = owner.getClass();
Field field = ownerClass.getField(fieldName);
Object property = field.get(owner);
return property;
}
//Class ownerClass = owner.getClass():得到该对象的Class。
//Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。
//Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。
}
3. 得到某个类的静态属性
public static void main(String[] args) throws Exception {
Object getStaticProperty(String className, String fieldName)throws Exception {
Class ownerClass = Class.forName(className);
Field field = ownerClass.getField(fieldName);
Object property = field.get(ownerClass.newInstance());
return property;
}
//Class ownerClass = Class.forName(className) :首先得到这个类的Class。
//Field field = ownerClass.getField(fieldName):和上面一样,通过Class得到类声明的属性,获得是公有字段。
//Object property = field.get(ownerClass.newInstance()) :这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。
方法: Method
Class类中的方法:
public Method[] getMethods() 获取所有的公共方法(包含父类的)
public Method[] getDeclaredMethods() 获取所有的方法(不包含父类)
public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) : 获取指定的方法(包含私有的)
Method类的方法:
public Object invoke(Object obj, Object... args)
调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了
public void setAccessible(boolean flag)
示例 :
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Object printmethod (Object obj, String methodname, Object[] args) throws Exception {
Class cl = obj.getClass();
// Method[] me=cl.getDeclaredMethods();
Method method = null;
Class[] c = null;
if (args != null) {
c = new Class[args.length];
for (int i = 0; i < args.length; i++) {
c[i] = args[i].getClass();
}
}
if (c == null) {
method = cl.getMethod(methodname);
} else {
method = cl.getMethod(methodname, c);
}
return method.invoke(obj, args);
}
}
}
5.构造器Constructor
//获取字节码文件
Class c = Class.forName("ConstractorText.Person");
//创建空参数构造方法
Constructor co = c.getConstructor();
co.newInstance(null);
//创建带参数的构造方法
Constructor con = c.getConstructor(String.class,int.class,String.class);//编译时 和 运行时
//创建对象
Object obj = con.newInstance("阿童木",11,"qinhuadao");
System.out.println(obj);
6.改变字段的值
字段: Field
Class中的方法:
public Field[] getFields() : 获取 public 修饰的 所有字段
public Field[] getDeclaredFields(): 获取所有的字段(包含私有)
public Field getField(String name): 获取指定的字段
public Field getDeclaredField(String name): 获取指定的字段(包含私有)
Field中的方法:
public void set(Object obj, Object value): 为指定对象中的当前字段, 赋值
步骤:
a: 创建class字节码文件对象
b: 获取指定的字段,如果是非public 修饰的字段, 需要 暴力访问
c: 对字段进行操作
示例 :
-
//创建class字节码文件对象
Class c = Class.forName("HomeText.Person");
//创建构造函数
Constructor con = c.getDeclaredConstructor();
//创建对象
Object obj = con.newInstance();//person
//创建获取指定字段
Field addressfield = c.getField("addresss");
addressfield.set(obj, "中国");
System.out.println(obj);
System.out.println("------------");
//获取私有成员变量,需利用暴力反射
//创建获取指定字段
Field nameField = c.getDeclaredField("name");
//暴力反射
nameField.setAccessible(true);
nameField.set(obj, "柳迪");
System.out.println(obj);
---------------------- 黑马程序员 Android培训、期待与您交流! ---------------------