反射的基本概念与Class、Constructor、Method、Field的基本应用
·反射的基本概念
在正常情况下,如果要使用一个类,则必须按照如下步骤操作:
·使用import导入类所在的包(类:java.lang.Class)
·明确使用类名称或者接口名称定义对象
·通过关键字new进行类对象实例化(构造方法:java.lang.reflect.Constructor)
·产生对象可以使用"对象.属性"进行类中属性的调用(属性:java.lang.reflect.Field)
·通过"对象.方法()"调用类的中方法(方法:java.lang.reflect.Method)
而反射的过程,不需要有明确类型的对象,所有的对象使用Object表示:
·可以直接利用Object与反射机制的混合 调用类中的方法。
·Class、Constructor、Method、Field的基本应用
1、Class类
Class类是整个反射操作的源头,而这个类的定义如下:
但是要使用Class类进行操作,就必须首先参数Class类的实例对象,而有如下三种方式可以产生Class类的实例对象:
·方式一:Object类提供了一个返回Class类对象的方法:public Class<?>getClass();
·方式二:利用"类.class"取得
·方式三:利用class类的static方法取得:
public static Class<?>forName(String className)Throws ClassNotFoundException
如果是程序设计的人员,使用最多的是forName()方法,如果是使用者,肯定会使用"类.class",而工厂设计模式最好利用反射机制进行解耦合。
2、利用反射实例化对象
Class类如果使用了forName()方法之后,就可以使用Class类定义的newInstance()方法默认去调用类之中的无参构造方法 Class<?> cls = Class.forName("CollectionStudy.Student");
//相当于关键之new实例对象,等价于:Object obj = new Student();
Object obj = cls.newInstance();
全局代码:
执行输出
到此非常清楚的发现,在整个编写过程即使完全不知道类结构,即使不导入包.类,也可以 进行类的对象实例化操作。
3、操作构造方法
但是如果使用反射实例化类对象,必须要求类中存在无参构造方法,因为默认使用Class类的newInstance()方法只能够找到无参构造方法。这个时候只能够取得类中的构造方法,传递所需要的参数后才可以执行。
在Class类中定义了可以取得一个类中构造方法的操作:
·取得类中的全部构造:public Constructor<?> [] getConstructors()
·取得类中的指定参数构造:public Constructor <T> getConstructor(Class<?>... parameterTypes)
范例:获得类中全部构造方法
输出结果:
所以如果现在要想进行指定构造方法的调用,就必须明白Constructor类。在此类中定义了一个实例化对象方法:
public T newInstance(Object... initargs)
范例:实例化student有参构造
Student类
正是因为如果通过构造方法实例化对象规格不统一,所以在进行简单JAVA类操作的时候,就必须给出无参构造方法。
4、调用类中的方法
取得一个类中的实例对象之后,下面主要的任务就是要调用类之中可以使用的操作方法,对于一个类中的方法,实际上有两类方法:
·取得父类继承而来的方法
-取得全部方法:public Method[] getMethods()
-取得指定方法:public Method getMethod(String name,Class<?>... parameterTypes)
·取得本类定义的方法
-取得全部方法:public Method[] getDeclaredMethods()
-取得指定方法:public Mehtod getDeclaredMethod(String name,Class<?>...parameterTypes)
但是以上操作在方法定义上区别不大,因为方法大部分是public,所以两种方式取得的结果是没有区别的。
范例:取得全部方法
再Method类中有一个至关重要的方法:
·调用:public Object invoke(Object obj,Object... args)
范例:反射调用类中的方法
Class<?> cls = Class.forName("CollectionStudy.Student");
Object obj = cls.newInstance();
Method setMethod = cls.getDeclaredMethod("setName", String.class);
Method getMethod = cls.getDeclaredMethod("getName");
setMethod.invoke(obj, "沉思");
System.out.println(getMethod.invoke(obj));
5、调用类中的属性(尽量不用)
关于类之中的属性,也可以用反射进行操作,而支持的方法也有两类:
·取得所有继承而来的属性:
-取得全部属性:public Field[] getFields()
-取得指定属性:public Field getField(String name)
·取得本类属性:
-取得全部属性:public Field[] getDeclaredFields()
-取得指定属性:public Field getDeclaredField(String name)
范例:取得一个类中的全部属性
在Field类中还定义有进行属性调用的方法:
·设置属性内容:public void set(Object obj,Object value)
·取得属性内容:public Object get(Object obj)
在Constructor、Method、Field三个类上有一个共同的父类AccessiableObject,
在这个类中定义了可以取消封装的操作:
使用Field.setAccessible(true)
范例:直接操作属性
在开发中,只需要灵活使用Class、Constructor、Method、Field就可以使用反射进行一系列操作的代码实现。