2.1反射概述
Java反射机制:是指在运行时去获取一个类的变量 和方法信息。然后通过获取到的信息来创建对象,调用方法的一
种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展
获取Class类的对象
我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型的对象
这里我们提供三种方式获取Class类型的对象
●使用类的class属 性来获取该类对应的Class对象。举例: Student.class将 会返回Student类对应的Class对象
●调用对象的getClass0方法, 返回该象所属类对应的Class对象
该方法是Object类中的方法,所有的Java对象都可以调用该方法
●使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某
个类的全路径,也就是完整包名的路径
package com.test02; public class reflectDemo { public static void main(String[] args) throws ClassNotFoundException { // 1:使用类的class属性来获取该类对应的Class对象 Class<Student> c1 = Student.class; System.out.println(c1); System.out.println("---------"); Student s = new Student(); Class<? extends Student> c2 = s.getClass(); // 调用对象的getClass()方法 System.out.println(c2); System.out.println("-------------"); // 使用Class类中的静态方法forName(String className) Class<?> c3 = Class.forName("com.test02.Student"); System.out.println(c3); } }
反射获取构造方法并使用
Class类中用于获取构造方法的方法
数组:
●Constructor<?> ] getConstructors(): 返回所有公共构造方法对象的数组
●Constructor<?>[ getDeclaredConstructors0: 返回所有构造方法对象的数组
单个:
●Constructor<T> getConstructor(Class <?> .. parameterTypes):返回单个公共构造方法对象
●Constructor<T> getDeclaredConstructor(Class<?> .. parameterTypes):返回单个构造方法对象
Constructor类中用于创建对象的方法
●T newlnstance(Objec... initargs):根据指定的构造方法创建对象
//暴力反射
public void setAccessible(boolean flag):值为true,取消访问检查
package com.test02; /* 反射获取构造方法并使用 */ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class refelectDemo01 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获取class对象 Class<?> c1 = Class.forName("com.test02.Student"); // Constructor<?>[] getConstructors() 返回一个包含 Constructor对象的数组, // Constructor对象反映了由该 Class对象表示的类的所有公共构造函数。 Constructor<?>[] cons = c1.getConstructors(); // Constructor<?>[] getDeclaredConstructors() // 返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组。 Constructor<?>[] cons2 = c1.getDeclaredConstructors(); for(Constructor con:cons2) { System.out.println(con); } System.out.println("-----------"); // Constructor<T> getConstructor(Class<?>... parameterTypes) // 返回一个 Constructor对象,该对象反映由该 Class对象表示的类的指定公共构造函数。 // Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) // 返回一个 Constructor对象,该对象反映由此 Class对象表示的类或接口的指定构造函数。 //Constructor<?> con = c1.getConstructor(); //Constructor是供了-一个类的单个构造函数的信息和访问权限 // T newInstance(Object... initargs) // 使用由此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。 // // 基本数据类型也可以通过.Class得到对应的Class类型 //练习1 Constructor<?> con3 = c1.getConstructor(String.class, int.class, String.class); Object obj = con3.newInstance("林青霞",30,"西安"); System.out.println(obj); System.out.println("-----------"); // 练习2 通过反射实现如下的操作: // Student s = new Student( "林青霞"); // System. out. println(s); //暴力反射 // public void setAccessible(boolean flag)将此反射对象的accessible标志设置为指示的布尔值。 值为true表示反射对象 // 应该在使用Java语言访问控制时抑制检查。 值为false表示反射对象应该在使用Java语言访问控制时执行检查,并在类描述中指出变体。 Constructor<?> con4 = c1.getDeclaredConstructor(String.class); con4.setAccessible(true);//由于下面对私有构造方法 Object obj1 = con4.newInstance("林青霞"); System.out.println(obj1); } }
反射获取成员变量并使用
Class类中用于获取成员变量的方法
Field[ getFields():返回所有公共成员变对象的数组
Field[] getDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象
Field类中用于给成员变量赋值的方法
●void set(Object obj, Object value):给obj对象的成员变量赋值为value
package com.test02; /* 反射获取成员变量 */ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; public class reflectDemo02 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获取class对象 Class<?> c = Class.forName("com.test02.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 getField(String name) Field field = c.getField("address");//成员变量的引用对象 //获取无参构造方法创建对象 //FieLa提供有关类或接口的单个字段的信息和动态访问 //void set (object obj, object value) 将指定的对象参数中由此Field对象表示的字段设置为指定的新值 Constructor<?> con = c.getConstructor(); Object obj = con.newInstance(); field.set(obj, "北京");//给obj的成员变量field赋值为北京 System.out.println(obj); // Student s = new Student(); //····s.address = "西安"; //····System. out . println(s); System.out.println("----------------"); // Field getDeclaredField(String name) Field age = c.getDeclaredField("age"); System.out.println(age); //age对象的引用 } }
通过反射给成员变量赋值练习
package com.test02; /* 练习:通过反射实现如下操作 Students = ngw Student(); s.name = "林青霞"; s.age = 30; s.address = "西安"; System.out.printin(); */ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; public class reflectDemo03 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获取要反射的类的对象 Class<?> c = Class.forName("com.test02.Student"); //创建对象示例 // 通过有参构造赋值 // Constructor<?> con = c.getConstructor(String.class, int.class, String.class); // Object obj = con.newInstance("林青霞",30,"西安"); Constructor<?> con = c.getConstructor(); Object obj = con.newInstance(); System.out.println(obj); //通过反射成员变量赋值 Field name = c.getDeclaredField("name"); name.setAccessible(true); name.set(obj,"林青霞"); Field age = c.getDeclaredField("age"); age.setAccessible(true); age.set(obj,33); Field address = c.getField("address"); address.set(obj,"北京"); System.out.println(obj); // } }
反射获取成员方法并使用
Class类中用于获取成员方法的方法
●Method[ getMethods0: 返回所有公共成员方法对象的数组,包括继承的
●Method] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
●Method getMethod(String name, Class <?> .. parameterTypes):返回单个公共成员方法对象
●Method getDeclaredMethod(String name, Class <?> .. parameterTypes):返回单个成员方法对象
Method类中用于调用成员方法的方法
●Object invoke(Object obj, Object... args):调用obj对象的成员方法,参数是args,返回值是Object类型
package com.test02; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class reflectDemo04 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获取class对象 Class<?> c = Class.forName("com.test02.Student"); // Method[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映由该 Class对象表示的类或接口的所有公共方法, // 包括由类或接口声明的对象以及从超类和超级接口继承的类。 // Method[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映由 Class对象表示的类或接口的所有声明方法, // 包括public,protected,default(package)访问和私有方法,但不包括继承方法。 Method[] Methods = c.getDeclaredMethods(); for (Method method : Methods) { System.out.println(method); } // Method getMethod(String name, Class<?>... parameterTypes) 返回一个 方法对象, // 该对象反映由该 Class对象表示的类或接口的指定公共成员方法。 // Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 方法对象, // 它反映此表示的类或接口的指定声明的方法 Class对象。 Method m = c.getMethod("method1"); //获取无参构造方法创建对象 Constructor<?> con = c.getConstructor(); Object obj = con.newInstance(); //在类或接口上提供有关单- 方法的信息和访问权限 // Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法。 //0bject: 返回值类型 //obj:调用方法的对象 //args:方法需要的参数 m.invoke(obj); // Student s = new Student(); // s. method1( ) ; } }
练习:通过反射实现如下操作
Student s = new Student();
s . method1();
s. method2("林青霞");
String ss = s.method3( "林青霞", 30);
System. out. println(ss);
s. function();
package com.test02; /* 练习:通过反射实现如下操作 Student s = new Student(); s . method1(); s. method2("林青霞"); String ss = s.method3( "林青霞", 30); System. out. println(ss); s. function(); */ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class reflectDemo05 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获取类的对象 Class<?> c = Class.forName("com.test02.Student"); // Student s = new Student(); Constructor<?> con = c.getConstructor() ; Object obj = con.newInstance(); // s . method1(); // invoke调用对象 Method method1 = c.getMethod("method1"); method1.invoke(obj); // s. method2("林青霞"); Method method2 = c.getMethod("method2", String.class); method2.invoke(obj,"林青霞"); // String ss = s.method3( "林青霞", 30); Method method3 = c.getMethod("method3", String.class, int.class); Object ss = method3.invoke(obj, "林青霞", 30); System.out.println(ss); // s. function(); Method function = c.getDeclaredMethod("function"); function.setAccessible(true); function.invoke(obj); } }
反射练习之越过泛型检查
package com.test02; /* 练习1:我有一个Arraylist<Integer>集合, 现在我想在这个集合中添加一-个字符串数据,如何实现? */ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; public class refiectDemo06 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { //创建集合 ArrayList<Integer> array = new ArrayList<Integer>(); array.add(10); array.add(20); array.add(30); // array.add("hello"); Class<? extends ArrayList> c = array.getClass(); Method m = c.getMethod("add", Object.class); m.invoke(array, "hello"); System.out.println(array); } }
反射运行配置文件