反射

一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖(反射)出类的各个组成部分。
本人在下面的反射例子中以注释的形式把所理解的东西写了出来

Person类:

 1 import java.util.List;

 2 

 3 public class Person {

 4 

 5     /*

 6      * 1.构造方法

 7      */

 8     //无参的

 9     public Person(){

10         System.out.println("无参的构造方法!");

11     }

12     //一个参数,类型为String的

13     public Person(String name){

14         System.out.println("name:" + name);

15     }

16     //一个参数,类型为int的,且为私有的

17     private Person(int age){

18         System.out.println("age:" + age);

19     }

20     //参数为两个参数

21     public Person(String name, int age){

22         System.out.println(name + "的年龄:" + age + "岁");

23     }

24     //参数为List的

25     public Person(List list){

26         System.out.println("list:" + list);

27     }

28     

29     /*

30      * 2.普通方法

31      */

32     //1、无参

33     public void methodTest(){

34         System.out.println("这是无参的普通方法!");

35     }

36     

37     //2、一个参数

38     public void methodTest(String name){

39         System.out.println("名字:" + name);

40     }

41     //3、一个参数私有的

42     private void methodTest(int age){

43         System.out.println("年龄:" + age);

44     }

45     //4、两个参数静态的

46     public static void methodTest(String name, int age){

47         System.out.println(name + "的年龄:" + age);

48     }

49     //5、main方法

50     public static void main(String[] args) {

51         System.out.println("main方法:");

52     }

53     

54     /*

55      * 3.字段

56      */

57     public String name = "张三";

58     private int age = 25;

59     private static String password = "PaSs1111";

60 }

测试代码:

  1 import java.lang.reflect.Constructor;

  2 import java.lang.reflect.Field;

  3 import java.lang.reflect.InvocationTargetException;

  4 import java.lang.reflect.Method;

  5 import java.util.ArrayList;

  6 import java.util.List;

  7 

  8 import org.junit.Test;

  9 

 10 public class ReflectTest {

 11 

 12     /**

 13      * @功能:反射

 14      * @介绍:

 15      *         clazz1.getConstructor()中的参数是可变参数,

 16      *     且用clazz1.getConstructor()只能反射出public型的,private反射不到

 17      *     如果想要得到private的构造方法,则需要用clazz.getDeclaredConstructor()来反射private的构造函数

 18      * @日期:2013-10-22

 19      */

 20 

 21     /*

 22      * 1.构造方法反射

 23      */

 24     @Test

 25     public void test1() throws Exception{

 26         //加载类(方式一) 参数中类名要全称

 27         Class clazz1 = Class.forName("cn.itcast.reflect.Person");

 28         //加载类(方式二)  ==> 实例化的时候构造方法直接运行

 29 //        Class clazz2 = new Person().getClass();

 30         //加载类(方式三)

 31 //        Class clazz3 = Person.class;

 32         //反射无参的构造方法,null表示无参

 33         Constructor c = clazz1.getConstructor(null);

 34         //new一个对象(正常情况下返回的是Object型的,这里强转为Person)

 35         Person p = (Person) c.newInstance();

 36     }

 37     

 38     @Test

 39     public void test2() throws Exception{

 40         //加载类

 41         Class clazz = Class.forName("cn.itcast.reflect.Person");

 42         //解剖(反射)出参数为String的构造方法(String.class)

 43         Constructor c = clazz.getConstructor(String.class);

 44         c.newInstance("张三");

 45     }

 46     

 47     @Test

 48     public void test3() throws Exception{

 49         //加载类

 50         Class clazz = Class.forName("cn.itcast.reflect.Person");

 51         //解剖(反射)出参数为int的构造方法(int.class)

 52         /*

 53          * 因为此时的构造方法为private的,所以正常的clazz.getConstructor(),不能反射出来

 54          * 此时就要用clazz.getDeclaredConstructor()来反射private的构造函数

 55          * 但解剖出来的构造方法不能直接new一个新的对象,还得能过c.setAccessible(true)修改一下属性(暴力反射)

 56          * ,这时才能进行new新对象,和正常的反射一样了

 57          */

 58         Constructor c = clazz.getDeclaredConstructor(int.class);

 59         //打开访问权限

 60         c.setAccessible(true);

 61         c.newInstance(25);

 62     }

 63     

 64     @Test

 65     public void test4() throws Exception{

 66         //加载类

 67         Class clazz = Class.forName("cn.itcast.reflect.Person");

 68         //反射方法

 69         Constructor c = clazz.getConstructor(String.class,int.class);

 70         //new

 71         c.newInstance("李四",25);

 72     }

 73     

 74     @Test

 75     public void test5() throws Exception{

 76         //加载类

 77         Class clazz = Class.forName("cn.itcast.reflect.Person");

 78         //反射方法

 79         Constructor c = clazz.getConstructor(List.class);

 80         //new

 81         List list = new ArrayList();

 82         list.add("zhangsan");

 83         list.add("lisi");

 84         list.add("wangwu");

 85         list.add("zhaoliu");

 86         c.newInstance(list);

 87     }

 88     

 89     /*

 90      * 2.普通方法反射

 91      */

 92     @Test

 93     public void test6() throws Exception{

 94         Person p = new Person();

 95         //加载类

 96         Class clazz = Class.forName("cn.itcast.reflect.Person");

 97         

 98         /*

 99          * 反射方法【clazz.getMethod("methodTest", null) 第一个参数为:方法名;第二个参数为:方法入参的类型】

100          * 这里方法入参为空,所以用null表示参数类型

101          */

102         Method method = clazz.getMethod("methodTest", null);

103         //method.invoke(p, null) 第一个参数要传一个对象,第二个为所反射的方法入参

104         method.invoke(p, null);

105     }

106     

107     @Test

108     public void test7() throws Exception{

109         Person p = new Person();

110         //加载类

111         Class clazz = Class.forName("cn.itcast.reflect.Person");

112         //反射

113         Method method = clazz.getMethod("methodTest", String.class);

114         //

115         method.invoke(p, "张三");

116     }

117     

118     @Test

119     public void test8() throws Exception{

120         Person p = new Person();

121         //加载类

122         Class clazz = Class.forName("cn.itcast.reflect.Person");

123         //私有的方法要用getDeclaredMethod来反射获取

124         Method method = clazz.getDeclaredMethod("methodTest", int.class);

125         //反射出来的方法此时还是private的,要强制打开访问权限

126         method.setAccessible(true);

127         //

128         method.invoke(p, 25);

129     }

130     

131     @Test

132     public void test9() throws Exception{

133         //加载类

134         Class clazz = Class.forName("cn.itcast.reflect.Person");

135         //反射

136         Method method = clazz.getMethod("methodTest", String.class, int.class);

137         /*

138          * 静态的可以不传对象,为:null即可

139          * (第一个参数为传对象的位置,后边的参数都是把反射方法的入参,invoke的“第二个参数”即为可变参数)

140          */

141         method.invoke(null, "李四", 25);

142     }

143     

144     @Test

145     public void test10() throws Exception{

146         //加载类

147         Class clazz = Class.forName("cn.itcast.reflect.Person");

148         Method method = clazz.getMethod("main", String[].class);

149         //main方法也是个静态方法

150         /*

151          * 关于下边注释的部分,是不可以用的,因为main方法中的参数为String[] args,是一个数组,在这里视为一个参数

152          * 在jdk1.4之前,没有“可变参数”,到了1.5以后才有的可变参数

153          * 那么,jdk1.4之前的method.invoke(String mehtodName, Object obj[])中

154          * 第二个参数用一个数组Object obj[]来传参的,在invoke中会把这个数组拆解成为一个个对应的参数

155          * 而jdk1.5是兼容jdk1.4的,所以,在jdk1.5中用数组来传参也可以,当然,它会把这个数组给拆解成几个参数

156          * 因此,在调用main方法的时候,要在外围再加一个数组,具体如下【数组参数1/2】

157          * 

158          * 注:反射参数为数组的方法都要注意

159          */

160         //method.invoke(null, new String[]{"123","234"});

161         //【数组参数1】

162         method.invoke(null, new Object[]{new String[]{"1234","5678","9012"}});

163         //【数组参数2】也可以这样(前边加一个Object可以欺骗一下程序,骗它为不是数组,其实传进去的确实为数组)

164         method.invoke(null, (Object)new String[]{"1234","5678","9012"});

165     }

166     

167     /*

168      * 3.字段反射

169      */

170     

171     @Test

172     public void test11() throws Exception{

173         Person p = new Person();

174         //加载类

175         Class clazz = Class.forName("cn.itcast.reflect.Person");

176         //参数为字段名称

177         Field field = clazz.getField("name");

178         //获取字段值,传一个对象进去

179         Object obj = field.get(p);

180         //获取字段的类型

181         Class type = field.getType();

182         //如果字段类型为String,则打印数值

183         if(type.equals(String.class)){

184             String value = (String) obj;

185             System.out.println(value);

186         }

187         //设置字段值,第一个参数传一个对象,第二个参数为修改的内容

188         field.set(p, "李四");

189         //打印一下,看看能不能通过反射来改变字段的值(结果:可以)

190         System.out.println(p.name);

191     }

192     

193     @Test

194     public void test12() throws Exception{

195         Person p = new Person();

196         //加载类

197         Class clazz = Class.forName("cn.itcast.reflect.Person");

198         //

199         Field field = clazz.getDeclaredField("age");

200         //私有字段,修改访问权限

201         field.setAccessible(true);

202         System.out.println(field.get(p));

203     }

204     

205     @Test

206     public void test13() throws Exception{

207         Person p = new Person();

208         //加载类

209         Class clazz = Class.forName("cn.itcast.reflect.Person");

210         Field field = clazz.getDeclaredField("password");

211         field.setAccessible(true);

212         /*

213          * 这里,password字段为私有且静态的字段,

214          * 但静态字段不同于静态方法和静态构造方法,field.get(p)中必须传对象

215          */

216         System.out.println(field.get(p));

217     }

218 }

 

你可能感兴趣的:(反射)