Class类与java.lang.reflect类库一起对反射进行了支持,该类库包含Field、Method和Constructor类,这些类的对象由JVM在启动时创建,用以表示未知类里对应的成员。这样的话就可以使用Contructor创建新的对象,用get()和set()方法获取和修改类中与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。另外,还可以调用getFields()、getMethods()和getConstructors()等许多便利的方法,以返回表示字段、方法、以及构造器对象的数组,这样,对象信息可以在运行时被完全确定下来,而在编译时不需要知道关于类的任何事情。
首先创建一个类
1 public class Per {
2 public String name="sunshine";
3 private int age=28;
4 public double weight=65.50;
5
6 public Per(){
7 System.out.println("测试反射获取公有无参构造函数");
8 }
9 private Per(String name){
10 this.name=name;
11 System.out.println("测试反射获取私有有参构造函数");
12 }
13 public Per(String name,int age){
14 this.name=name;
15 this.age=age;
16 System.out.println("测试反射获取公有有多个参数构造函数name:"+name+" age:"+age);17 }
18 public String methodT1(){
19 System.out.println("测试反射获取公有无参方法");
20 return null;
21 }
22 public String methodT1(String name,int age){
23 System.out.println("测试反射获取公有多个参方法");
24 System.out.println(name+":"+age);
25 return null;
26 }
27 private String methodT1(String name){
28 System.out.println("测试反射获取私有有参方法");
29 System.out.println("name:"+name);
30 return null;
31 }
32 public String methodT2(int[] arr,String[] str){
33 System.out.println("测试反射获取公有有数组参方法");
34 System.out.println("int[] arr:"+arr+"String[] str:"+str);
35 return null;
36 }
37 public static void main(String[] args) {
38 System.out.println("测试反射获取main方法");
39 }
40 }
1.使用java反射获取类的构造函数(公有、私有)(有参,无参)
1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.Field;
3 import java.lang.reflect.Method;
4
5 import org.junit.AfterClass;
6 import org.junit.BeforeClass;
7 import org.junit.Test;
8 /**
9 * 测试使用java反射获取类的构造函数并创建对象
10 * @author Sunshine
11 *
12 */
13 public class ReflectPer {
14 private static Class class1;
15 //因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个测试方法中重复创建
16 //注:@beforeclass在执行测试方法前运行
17 @BeforeClass
18 public static void beforeClass() throws Exception{
19 System.out.println("====测试方法启动前先加载类====");
20 class1 = Class.forName("myPractise.Per");//加载类
21 }
22 //获取类的公有无参构造函数,并创建对象
23 @Test
24 public void test1() throws Exception{
25 Constructor constructor = class1.getConstructor(null);//获取公有无参构造器,值为null代表获取无参构造器
26 Per per = (Per) constructor.newInstance(null);//创建对象,返回的是Object类型要强转
27 System.out.println(per.name);//可以调用类的属性-----成功
28 }
29 //获取类的公有参构造函数,并创建对象
30 @Test
31 public void test2()throws Exception{
32 Constructor constructor = class1.getConstructor(String.class,int.class);//获取公有多个参数构造器,参数为构造器中参数的类型
33 Per per = (Per)constructor.newInstance("baby",24);//创建对象
34 }
35 //获取类的私有有参构造函数,并创建对象
36 @Test
37 public void test3()throws Exception{
38 Constructor constructor = class1.getDeclaredConstructor(String.class);//获取公有多个参数构造器,参数为构造器中参数的类型
39 constructor.setAccessible(true);//暴力反射,只有将属性设置为true才可以创建对象
40 Per per = (Per)constructor.newInstance("baby");
41 System.out.println(per.weight);//可以调用类的属性-----成功
42 //注:通常情况下一个类不可以访问另一个类的私有的属性,方法。。但是通过java反射可以
43 }
44 @AfterClass
45 public static void afterClass(){
46 System.out.println("===测试完成将对象赋值为null===");
47 }
48 }
2.使用java反射获取类的方法(公有、私有)(有参,无参)
1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.Field;
3 import java.lang.reflect.Method;
4
5 import org.junit.AfterClass;
6 import org.junit.BeforeClass;
7 import org.junit.Test;
8 /**
9 * 测试使用java反射获取类方法
10 * @author Sunshine
11 *
12 */
13 public class ReflectPer {
14 private static Class class1;
15 private static Per per;
16 //因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个方法中重复创建
17 //注:@beforeclass在执行测试方法前运行
18 @BeforeClass
19 public static void beforeClass() throws Exception{
20 System.out.println("====测试方法启动前先加载类====");
21 class1 = Class.forName("myPractise.Per");//加载类
22 per = (Per) class1.getConstructor(null).newInstance(null);//使用反射创建对象
23 }
24
25 //获取类的公有无参方法
26 @Test
27 public void test4()throws Exception{
28 Method method = class1.getMethod("methodT1", null);//获取指定的方法,参数为方法名和该方法的参数类型,因为我们这是测试无参的方法,所以传入null
29 method.invoke(per, null);//使用invoke方法来调用,参数为指定对象,该方法传入的参数,因为我们这是测试无参的方法,所以传入null
30 }
31 //获取类的公有有参方法
32 @Test
33 public void test5()throws Exception{
34 Method method = class1.getMethod("methodT1", String.class,int.class);//获取指定的方法,参数为方法名和该方法的参数类型
35 method.invoke(per, "sunshine",25);//使用invoke方法来调用,参数为指定对象,该方法传入的参数
36 }
37 @Test
38 public void test6()throws Exception{
39 Method method = class1.getDeclaredMethod("methodT1", String.class);//获取指定的方法,参数为方法名和该方法的参数类型
40 method.setAccessible(true);//暴力反射,默认为false,未设置则调用类的私有方法不成功
41 method.invoke(per, "sunshine");//使用invoke方法来调用,参数为指定对象,该方法传入的参数
42 System.out.println(method.getReturnType());//获取到该类指定方法的返回值类型
43 }
44 @Test
45 public void test7()throws Exception{
46 Method method = class1.getMethod("methodT2", int[].class,String[].class);
47 method.invoke(per, new int[]{1,2},new String[]{"AA","BB"});
48 }
49 //获取某个类的main方法比较特殊也可以说是只要传入的参数为单个数组特殊
50 //jdk5之后新增特性--可变参数
51 //在加载时会将传入的数组进行拆分,这样就会报错,java.lang.IllegalArgumentException: wrong number of arguments 错误的参数个数
52 //这时候我们可以欺骗一下虚拟机,告诉他我们传入的是一个对象将new String[]{"AA","BB"}换成(Object)new String[]{"AA","BB"}
53 @Test
54 public void test8()throws Exception{
55 Method method = class1.getMethod("main",String[].class);
56 method.invoke(per,(Object)new String[]{"AA","BB"});
57 }
58 @AfterClass
59 public static void afterClass(){
60 System.out.println("===测试完成将对象赋值为null===");
61 }
62 }
3.使用java反射获取类的属性(公有、私有)
1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.Field;
3 import java.lang.reflect.Method;
4 import java.util.Iterator;
5
6 import org.junit.AfterClass;
7 import org.junit.BeforeClass;
8 import org.junit.Test;
9
10 /**
11 * 测试使用java反射获取类的属性
12 *
13 * @author Sunshine
14 *
15 */
16 public class ReflectPer {
17 private static Class class1;
18 private static Per per;
19
20 // 因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个测试方法中重复创建
21 // 注:@beforeclass在执行测试方法前运行
22 @BeforeClass
23 public static void beforeClass() throws Exception {
24 System.out.println("====测试方法启动前先加载类====");
25 class1 = Class.forName("myPractise.Per");// 加载类
26 per = (Per) class1.getConstructor(null).newInstance(null);// 使用反射创建对象
27 }
28 // 公有属性
29 @Test
30 public void test9() throws Exception {
31 // 获取某个属性,参数是属性名
32 Field field = class1.getField("name");
33 // 输出属性值,需要传入指定对象
34 System.out.println(field.get(per));
35 // 获取属性的类型
36 System.out.println(field.getType());
37 // 获取多个属性
38 Field[] field1 = class1.getFields();
39 // 增强for循环Jdk1.5后的新特性,只适用于数组和实现了Iterator的集合
40 for (Field str : field1) {
41 System.out.println(str);
42 }
43 // 设置属性值
44 field.set(per, "baby");
45 System.out.println(field.get(per));
46 }
47 //私有属性
48 @Test
49 public void test10() throws Exception {
50 Field field = class1.getDeclaredField("age");
51 field.setAccessible(true);//暴力反射
52 System.out.println(field.get(per));
53 }
54
55 @AfterClass
56 public static void afterClass() {
57 System.out.println("===测试完成将对象赋值为null===");
58 }
59 }