综合实例
下面是一个使用Java反射的示例代码,该代码演示了如何使用反射API获取一个类的信息、创建对象、调用方法和访问成员变量等:
// 定义一个Person类 public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } // 使用反射API获取Person类的信息、创建对象、调用方法和访问成员变量等 public class ReflectionDemo { public static void main(String[] args) throws Exception { // 获取Person类的Class对象 Class<Person> clazz = Person.class; // 创建Person对象 Constructor<Person> constructor = clazz.getConstructor(String.class, int.class); Person person = constructor.newInstance("张三", 18); // 调用getName方法获取姓名 Method getNameMethod = clazz.getMethod("getName"); String name = (String) getNameMethod.invoke(person); System.out.println("姓名:" + name); // 访问age成员变量并修改其值 Field ageField = clazz.getDeclaredField("age"); ageField.setAccessible(true); ageField.setInt(person, 20); // 调用getAge方法获取年龄 Method getAgeMethod = clazz.getMethod("getAge"); int age = (int) getAgeMethod.invoke(person); System.out.println("年龄:" + age); } }
在该示例代码中,我们首先定义了一个Person类,然后使用反射API获取该类的Class对象,并通过该对象创建了一个Person对象。接着,我们使用反射API获取Person类的getName方法和getAge方法,并通过这些方法获取了该对象的姓名和年龄信息。最后,我们使用反射API获取Person类的age成员变量,并修改了其值。
注解1:
// 创建Person对象 Constructor<Person> constructor = clazz.getConstructor(String.class, int.class); Person person = constructor.newInstance("张三", 18);
这段代码演示了如何使用Java反射机制来调用类的构造方法创建对象。
首先,代码获取了Person类的Class对象,即
Class<Person> clazz = Person.class;
。接着,代码使用
getConstructor()
方法获取Person类的指定构造方法,即constructor = clazz.getConstructor(String.class, int.class);
。这个构造方法接收两个参数,一个String类型的name和一个int类型的age。然后,代码使用构造方法对象的
newInstance()
方法创建Person对象,并传入name和age参数,即Person person = constructor.newInstance("张三", 18);
。最终,代码得到了一个Person对象,可以对其进行操作。
注解2:
// 调用getName方法获取姓名 Method getNameMethod = clazz.getMethod("getName"); String name = (String) getNameMethod.invoke(person); System.out.println("姓名:" + name);
这段代码演示了如何使用Java反射机制来调用类的方法。
首先,代码获取了Person类的Class对象,即
Class<Person> clazz = Person.class;
。接着,代码使用
getMethod()
方法获取Person类的指定方法对象,即getNameMethod = clazz.getMethod("getName");
。这个方法不需要传入参数,返回类型为String。然后,代码使用
invoke()
方法调用Person对象的getName方法,即String name = (String) getNameMethod.invoke(person);
。invoke()
方法的第一个参数为要调用方法的对象,这里是person对象;第二个参数为可选参数,如果getName方法需要传入参数,则可以在这里传入。最后,代码将获取到的name值输出到控制台,即
System.out.println("姓名:" + name);
。注解3:
// 访问age成员变量并修改其值 Field ageField = clazz.getDeclaredField("age"); ageField.setAccessible(true); ageField.setInt(person, 20);
这段代码演示了如何使用Java反射机制来访问和修改类的成员变量。
首先,代码获取了Person类的Class对象,即
Class<Person> clazz = Person.class;
。接着,代码使用
getDeclaredField()
方法获取Person类的指定成员变量对象,即Field ageField = clazz.getDeclaredField("age");
。这个方法需要传入一个字符串参数,即成员变量的名称。然后,代码调用
setAccessible()
方法将成员变量的访问权限设为可访问,即ageField.setAccessible(true);
。这是因为age是一个private成员变量,必须设置为可访问才能修改它的值。接下来,代码使用
setInt()
方法修改person对象的age成员变量的值,即ageField.setInt(person, 20);
。setInt()
方法的第一个参数为要修改的对象,这里是person对象;第二个参数为要设置的值,这里是20。最后,代码修改后的person对象的age值就被成功地设置为了20。
注解4:
// 调用getAge方法获取年龄 Method getAgeMethod = clazz.getMethod("getAge"); int age = (int) getAgeMethod.invoke(person); System.out.println("年龄:" + age);
这段代码演示了如何使用Java反射机制来调用类的方法。
首先,代码获取了Person类的Class对象,即
Class<Person> clazz = Person.class;
。接着,代码使用
getMethod()
方法获取Person类的指定方法对象,即Method getAgeMethod = clazz.getMethod("getAge");
。这个方法需要传入一个字符串参数,即要调用的方法的名称。然后,代码使用
invoke()
方法调用getAge方法,即int age = (int) getAgeMethod.invoke(person);
。invoke()
方法的第一个参数为要调用的对象,这里是person对象;如果被调用的方法有参数,则后续参数需要按照方法参数列表传入。invoke()
方法的返回值为被调用方法的返回值,需要进行强制类型转换。最后,代码调用getAge方法获取到了person对象的年龄,并将其输出。
基础实例1 获取类对象(三种方式)
/*本类用于反射的测试*/ public class TestReflect { //1.可以创建程序的入口函数main()--此处不用 //2.通过单元测试方法,获取目标类Student对应的字节码对象 @Test public void getClazz() throws ClassNotFoundException { //练习获取字节码对象的3种方式 Class<?> clazz1 = Class.forName("com.review.Student"); Class<?> clazz2 = Student.class; Class<?> clazz3 = new Student().getClass(); //打印的是Student类对应的字节码对象 System.out.println(clazz1);//class com.reflection.Student //获取Student类对应的字节码对象clazz1的名字 System.out.println(clazz1.getName());//com.reflection.Student //通过Student类对应的字节码对象,获取Student类的类名 System.out.println(clazz1.getSimpleName()); //通过Student类对应的字节码对象,获取Student类对应的包对象 System.out.println(clazz1.getPackage()); //通过Student类对应的字节码对象,先获取Student类对应的包对象,再获取这个包对象的名字 System.out.println(clazz1.getPackage().getName()); } }
基础实例2 获取成员变量(Class.forName)
/**本类用来测试反射*/ public class TestReflect { //3.通过单元测试方法练习引用类型数组的定义与遍历 @Test public void getStu() { //1.创建Student类的3个对象 Student s1 = new Student("张三", 3); Student s2 = new Student("李四", 4); Student s3 = new Student("王五", 5); //2.创建数组将刚刚的3个对象存入数组中 Student[] s = {s1, s2, s3}; //3.直接打印数组,查看数组中的元素 System.out.println(Arrays.toString(s)); //4.遍历学生数组,拿到每一个学生对象,做进一步的操作 for (Student stu : s) { //System.out.println(stu); stu.play();//通过遍历到的对象,执行play() System.out.println(stu.age);//通过遍历到的对象,打印age属性 } } //4.通过单元测试方法,获取Student类中的成员变量 @Test public void getFie() throws ClassNotFoundException { //1.获取Student类对应的字节码对象 Class<?> clazz = Class.forName("com.review.Student"); //2.通过Student类对应的字节码对象获取Student类中的成员变量们 Field[] fs = clazz.getFields(); //3.遍历数组,获取Student类中的每个成员变量的具体信息 /*注意!目前成员变量的修饰符必须是public的才能获取到*/ for(Field f : fs){ System.out.println(f.getName());//通过本轮循环到的字段对象获取字段名 System.out.println(f.getType());//通过本轮循环到的字段对象获取字段的类型 } } }
基础实例3 通过字节码对象获取类的成员方法(Class.forName)
/**本类用来测试反射*/ public class TestReflect { //5.通过单元测试方法,获取Student类中的成员方法 @Test public void getFunction() { //1.获取Student类对应的字节码对象 Class<?> clazz = Class.forName("com.review.Student"); //2.通过Student类对应的字节码对象获取Student类中的成员方法们 Method[] ms = clazz.getMethods(); //3.通过高效for循环遍历数组,拿到每一个方法对象 for (Method m : ms) { System.out.println(m);//直接打印遍历到的方法对象 System.out.println(m.getName());//通过方法对象获取方法名 Class<?>[] pt = m.getParameterTypes();//通过方法对象获取方法所有参数的数组 System.out.println(Arrays.toString(pt));//打印方法参数的数组 } } }
基础实例4 通过字节码对象获取类的构造方法(Class.forName)
/**本类用来测试反射*/ public class TestReflect { //6.通过单元测试方法,获取Student类中的构造方法 @Test public void getCons() { //1.获取字节码对象 Class<?> clazz = Class.forName("com.review.Student"); //2.通过字节码对象获取目标类Student的构造方法们 Constructor<?>[] cs = clazz.getConstructors(); //3.通过高效for循环遍历数组 for(Constructor c : cs){ System.out.println(c.getName());//打印本轮遍历到的构造方法的名字 Class[] pt = c.getParameterTypes();//通过本轮遍历到的构造函数对象获取构造函数的参数类型 System.out.println(Arrays.toString(pt));//打印参数类型 } } }
基础实例5 创建对象(Class.forName)
/**本类用来测试反射*/ public class TestReflect { //7.通过单元测试方法,创建Student目标类的对象 @Test public void getObject() throws Exception { //1.获取字节码对象 Class<?> clazz = Class.forName("com.review.Student"); //2.通过反射技术创建目标类的对象,注意抛出异常 /*反射创建对象方案1: 使用 目标类 的 无参构造 创建对象 */ Object o = clazz.newInstance(); System.out.println(o);//这一步已经获取到了对象Student{name='null', age=0} /*反射创建对象方案2: 使用 目标类 的 全参构造 创建对象 * 思路: * 1.先获取指定的构造函数对象,注意需要指定构造函数的参数,传入的是.class字节码对象 * 2.通过刚刚获取到的构造函数对象创建Student目标类的对象,并且给对象的属性赋值 * */ //3.获取目标类中指定的全参构造 Constructor<?> c = clazz.getConstructor(String.class, int.class); //System.out.println(c); //4.通过获取到的构造函数:创建对象 + 给对象的属性赋值 Object o2 = c.newInstance("赵六", 6); System.out.println(o2); } }