反射------韩春龙
反射概述:
java反射机制:
是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大增强程序的灵活性,程序不用再编译器就能完成确定,在运行期仍然可以扩展。
获取Class类的对象:
如果想使用反射去使用一个类,首先要获取到该类的字节码文件对象,集类型为Class类型的对象,以下是三种获取Class类型的对象的方式:
-
使用类的Class属性来获取该类对应的Class对象,举例:Student.Class将会返回Student类对应的Class对象;
-
使用对象的getClass()方法,返回该对象所属类对应的Class对象,该方法是Object类中的方法,所有的Java对象都可以调用该方法
-
使用Class类中的静态方法forName(String classname),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的名称
代码举例:
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//使用类的Class属性来获取该类对应的Class对象
Class<Student> c1=Student.class;
System.out.println(c1);
Class<Student> c2=Student.class;
System.out.println(c1==c2);
System.out.println("----------------");
//使用对象的getClass()方法,返回该对象所属类对应的Class对象
Student s=new Student();
Class<? extends Student> c3=s.getClass();
System.out.println(c1==c3);
//使用Class类中的静态方法forName(String classname)
Class<?> c4=Class.forName("comflect01.Student");
System.out.println(c1==c4);
}
}
反射获取构造方法并使用:
Class中用于获取构造方法的方法:
-
Constructor<?>[] getConstructors() ,返回一个包含 所有公共构造方法对象的数组
-
Constructor<?>[] getDeclaredConstructors() 返回所有构造函数对象的数组。
-
Constructor getConstructor(Class<?>… parameterTypes) 返回单个公共构造方法对象。
-
Constructor getDeclaredConstructor(Class<?>… parameterTypes) 返回单个 构造方法对象。
代码举例:
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取Class对象
Class<?> c=Class.forName("comflect01.Student");
//Constructor<?>[] getConstructors() 返回一个包含 Constructor对象的数组,
// Constructor对象反映了由该 Class对象表示的类的所有公共构造函数。
//Constructor<?>[] getDeclaredConstructors() 返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组。
//Constructor<?>[] cons = c.getConstructors();
Constructor<?>[] cons=c.getDeclaredConstructors();
for(Constructor con:cons){
System.out.println(con);
}
System.out.println("------------------");
//Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor对象,'
// 该对象反映由该 Class对象表示的类的指定公共构造函数。
//Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor对象,
// 该对象反映由此 Class对象表示的类或接口的指定构造函数
//参数,你要获取的构造方法的参数的个数和数据类型对应的字节码文件对象
Constructor<?> con =c.getConstructor();
//Constructor提供了一个类的单个构造函数的信息和访问权限。
//T newInstance(Object... initargs) 使用由此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。
Object obj = con.newInstance();
System.out.println(obj);
Student s=new Student();
System.out.println(s);
}
}
反射获取成员变量并使用:
反射中获取成员变量的方法:
- Field[] getFields()返回所有成员变量对象的数组
- Field[] getDeclaredFields() 返回所有成员变量对象的数组
- Field getField(String name);返回单个成员变量对象
- Field getDeclaredField(String name)返回单个成员变量对象
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取Class对象
Class<?> c = Class.forName("comflect01.Student");
//Field[] getFields() 返回一个包含 Field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段.
//Field[] getDeclaredFields() 返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段。
//Field[] fields = c.getFields();
Field[] fields = c.getDeclaredFields();
for (Field field : fields){
System.out.println(field);
}
System.out.println("------------------");
//Field getField(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段。
//Field getDeclaredField(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段。
Field addressfields1 = c.getField("address");
// //实现:如下
// Student s=new Student();
// s.address="西安";
// System.out.println(s);
//获取无参构造方法创建对象
Constructor<?> con=c.getConstructor();
Object obj=con.newInstance();
// Field提供有关类或接口的单个字段的信息和动态访问。
//void set(Object obj, Object value) 将指定的对象参数中由此 Field对象表示的字段设置为指定的新值
addressfields1.set(obj,"西安");
System.out.println(obj);
}
}
反射获取成员方法:
Class中用于获取成员变量的方法:
-
Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
-
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
-
Method getDeclaredMethod(String name, Class<?>… parameterTypes):返回单个成员方法
-
Method getMethod(String name, Class<?>… parameterTypes):返回单个公共成员方法
Method类中用于调用成员方法的方法 -
Method类中用于调用成员方法的方法
Object invoke(Object obj,Object…args);调用obj成员方法,参数是args,返回值是Object类型
代码举例
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取Class对象
Class<?> c = Class.forName("comflect01.Student");
//Method[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映由该 Class对象表示的类或接口的所有公共方法,
// 包括由类或接口声明的对象以及从超类和超级接口继承的类。
//Method[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映由 Class对象表示的类或接口的所有声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承方法。
//Method[] methods = c.getMethods();
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("-----------------------");
//Method getMethod(String name, Class<?>... parameterTypes) 返回一个 方法对象,该对象反映由该 Class对象表示的类或接口的指定公共成员方法。
//Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 Class对象。
//public void method1()
Method m = c.getMethod("method1");
//获取无参构造方法创建对象
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//在类或接口上提供有关单一方法的信息和访问权限
//Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法。
//Object:返回值类型
//obj :调用方法的对象
//args : 方法需要的参数
m.invoke(obj);
// //实现如下操作:
// Student s =new Student();
// s.method1();
}
}
如何体现反射的优点:(举例如下)
越过泛型的检查
public class ReflectDemo01 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//创建集合
ArrayList<Integer> list=new ArrayList<Integer>();
//得到反射的Class对象
Class<? extends ArrayList> c = list.getClass();
//使用add()方法添加字符串
Method m = c.getDeclaredMethod("add", Object.class);
m.invoke(list,"hello");
m.invoke(list,"world");
m.invoke(list,"java");
//本来正常情况下该list集合的泛型是 Integer 类型的,因此无法直接给其添加String类型的元素,但是使用反射成功跨过泛型的检查
System.out.println(list);
}
}