反射主要解决动态编程,即使用反射时,所有的对象生成是动态的,因此调用的方法也是动态的.反射可以简化开发,但是代码的可读性很低.
很多主流框架都使用了反射技术.像ssh框架都采用两种技术 xml做配置文件+反射技术。
如何获得对象Class
1.针对每一个对象.getCalss(),可以得到对应的Class.
2.Class.forName(String),String的写法:包名.类名.就会创建包名.类名对应的那个对象
注:2只适用于引用类型
3.对于基本类型:封装类.TYPE代表了对应的基本类型的Class对象.Integer.TYPE对应的是int的Class对象
注:3只适用于基本类型
4.类型,Class。<第4种是通用的.>
上面的4种方法,只有方法2是动态的,只要换一个包就可以了.它具有动态潜质.所以真正意义的想体现动态编程只能使用方法2。
每种类型的Class对象只有一个,即他们的地址只有一个,但是不同类型是不同的。
所以下面的打印结果都为true。
//对与引用类型 Class c1 = "".getClass(); Class c2 = Class.forName("java.lang.String"); Class c3 = String.class; System.out.println(c1 ==c2);//true //对于基本类型 Class num1 = Integer.TYPE; Class num2 = int.class;
System.out.println(num1 == num2);//true
反射获取类中的成员
1、获取属性Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 Field[] getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
2、获取方法Method getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 T newInstance() 创建此 Class 对象所表示的类的一个新实例。 <new Instance()可以动态的创建对象> String toString() 将对象转换为字符串。
注意:new Instance()调用的是无参构造,如果该类没有无参构造方法,则newInstance()会产生异常.
有declared的方法是支持私有,但是不支持继承,无declared的方法支持继承,不支持私有,且只能取出public的东西.
因此取属性的时候一般来说是带declared的,因为属性一般都是私有的,取方法时一般是不带declared的,取构造时一般也是不带declared的.
利用反射对成员赋值
1、属性赋值
Field中的方法
Object get(Object obj)
返回指定对象上此 Field 表示的字段的值。
Field f = c.getXXField(属性名);
值 = f.get(对象);
void set(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
f.set(对象,值);
Class<?> getType()
返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。
用于获取属性的类型(返回Class对象).
Class c = Student.class; Object obj = c.newInstance(); //创建Student类的对象 Field f = c.getDeclaredField("name"); //获取name属性 f.setAccessible(true); //设置私有可以访问. f.set(obj, "zhangsan"); System.out.println(f.get(obj)); //获取obj的name属性的值.
2、调用方法
对象.方法名(值1,2,3);
Method m = c.getMethoed(方法名,参数类型...);
m.invoke(对象,方法调用的参数 )如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。
Class c = Class.forName("com.clazz.reflect.Student");
Object obj = c.newInstance(); //创建Sutdent对象.
Method msetName = c.getMethod("setName", String.class);//obj无须转换类型
msetName.invoke(obj, "zhangsan");//调用方法setName, 并传参.
Method msetId = c.getMethod("setId", int.class);
msetId.invoke(obj, 409090202);
System.out.println(obj);