一.Java反射机制
1.Class类是反射操作的源头,也就是说所有的反射操作都应该通过Class类完成,这个类的对象可以通过三种方式实例化..
第一种:利用object类中的getclass方法,必须有明确的实例化对象时使用
第二种:利用"类.class"方式获得实例化对象.
第三种:利用class类的static方法取得
实例化class类对象public static Class<?> forName(String className) throws ClassNotFoundException
他的好处是可以直接编写字符串
2.通过反射实例化对象
如果要实例化对象,本质上来讲必须要有关键字new才可以实现,但是现在有了反射之后就变了
在Class类中提供了如下的方法public T newInstance() throws InstantiationException,IllegalAccessException进行实例化对象.
反射实例化对象最终也要调用无参构造方法进行实例化操作.如果没有无参构造方法则会出现实例化异常.
3.为什么要使用反射
反射机制代码量并不比new的少,使用起来也并不方便,那么为什么要使用反射呢?
首先我们知道,Java中有三种设计模式:单例模式,工厂模式,代理模式.
在工厂模式中我们就可以利用反射对工厂设计模式进行修正.工厂设计模式的本质在于想要去取得借口的实例化对象不能使用关键字new,而应该通过工厂取得(只要是自己写的借口想要取得实例化对象,99%要写工厂[理论原则]).
如果说接口增加了子类,那么工厂类就需要作出修改,这个接口可能源源不断的增加新的子类,所以这时候的工厂类的设计就存在新的问题了.那么现在的关键性问题就在于new上了,new就是造成本次设计缺陷的最大元凶,导致代码可扩展性非常差,我们就可以用反射进行修改.
但是我们并不意味着就不使用关键字new了.只是反射可扩充性比new大.
4.调用构造方法
利用Class类中的newInstance方法是可以取得类的实例化对象,但是这样做有一定的问题,因为他只能调用类中的无参构造方法.
如果类中没有提供无参构造方法,那么就必须明确的调用指定的构造方法实现对象的实例化操作.要想实现这样的操作,那么必须找到构造方法的定义.
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException.
找到了java.lang.reflect.Constructor类之后再此类中提供一个实例化对象的方法:实例化对象:public T newInstance(Object... initargs) throws InstantiationException,IllegalAccessException,IllegalArgumentException,InvocationTargetException
使用它就可以调用类中的有参构造方法.
5.调用普通方法
类中的普通方法是在取得了奔雷的实例化对象之后才可以进行调用的操作.所以即便使用了反射进行方法的调用,那么也必须使用newInstance()取得实例化对象,在Class类中定义有如下取得方法的操作:public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException.
getMethod()方法返回的是java.lang.reflect.Method()类对象,在这个勒种有一个最为重要的方法:调用方法:public Object invoke(Object obj,Object... args) throws IllegalAccessException, IllegalArgumentException,InvocationTargetException
以后程序中如果给了属性名称,类的完整名称,而后可以进行自动的赋值操作,那么基本上就是反射机制在里面起作用.
6.调用成员
在类中的成员需要考虑两种因素(class类定义的方法)
1.父类继承而来的成员:public Field getField(String name) throws NoSuchFieldException, SecurityException;
2.本类定义的成员:public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException
在Java中使用java.lang.reflect.Field类描述成员,在这个类中有两个方法:
取得成员内容:public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException
设置成员内容:public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException
但是所有属性几乎都用private封装,所以想要取消封装的影响,可以调用Field父类的方法:java.lang.reflect.AccessibleObject.public static void setAccessible(AccessibleObject[] array, boolean flag) throws SecurityException
几乎类中的一切定义形式都可以用反射进行,以上就是反射的主要操作.