java小故事_Java反射的小故事

Java反射的小故事:

首先定义一个Java类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.xiaoysec.test;2

3 public classPerson {4 privateString name;5 privateString sex;6 private intid;7

8 publicString getName() {9 returnname;10 }11

12 public voidsetName(String name) {13 this.name =name;14 }15

16 publicString getSex() {17 returnsex;18 }19

20 public voidsetSex(String sex) {21 this.sex =sex;22 }23

24 public intgetId() {25 returnid;26 }27

28 public void setId(intid) {29 this.id =id;30 }31

32 public Person(String name, String sex, intid) {33 this.name =name;34 this.sex =sex;35 this.id =id;36 }37 private voidshow(){38 System.out.println("name is:"+this.name);39 System.out.println("sex is:"+this.sex);40 System.out.println("id is:"+this.id);41 }42 public static voidmain(String[] args){43 System.out.println(args[0]);44 }45 }

View Code

在类中定义了一些方法,尤其注意的是方法的访问权限,show()方法被定义为了私有方法,以前上课的时候只是说private修饰的方法或属性只能在类的内部进行访问,那么这句话有没有问题呢?

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.xiaoysec.test;2

3 importjava.lang.reflect.Constructor;4 importjava.lang.reflect.Field;5 importjava.lang.reflect.Method;6

7 importorg.junit.Test;8

9 public classClasstest {10 privateString simplename;11

12 @Test13 public voidtest() {14

15 try{16 Class c = Class.forName("com.xiaoysec.test.Person");17 Constructor constructor = c.getConstructor(newClass[] {18 String.class, String.class, int.class});19 Person p = (Person) constructor.newInstance("xiaoysec", "sex", 19);20 Method m = c.getDeclaredMethod("show", null); //获取的是private权限的show方法

21 m.setAccessible(true); //强行打开访问权限 使用发射可以访问private方法22 //面试的时候如果被问及private是否可以被访问应该 回答23 //普通的方式只能在类的内部访问 而通过反射可以访问private

24 m.invoke(p, null);25 System.out.println(c.getName());26 System.out.println("-------------");27 Field f = c.getDeclaredField("name");28 f.setAccessible(true);29 Class fieldtype =f.getType();30 System.out.println(fieldtype);31 Object o =f.get(p);32 System.out.println(o.getClass()); //此处返回的是class java.lang.String

33 System.out.println(o);34 System.out.println("--------------");35 Method mainmethod = c.getMethod("main", String[].class); //main方法的反射36 //mainmethod.invoke(p, new String[]{"xiaoysec"});//argument type37 //mismatch

38 mainmethod.invoke(p, (Object) new String[] { "xiaoysec"});39 //mainmethod.invoke(p,new Object[]{new String[]{"xiaoysec"}});40 // //此方法也是对的

41 } catch(Exception e) {42 //TODO Auto-generated catch block

43 e.printStackTrace();44 }45

46 }47

48 }

View Code

请注意setAccessible(true)这点,通过设置,就可以访问private修饰的方法了。

另外在上面的代码中值得一提的是main方法的反射

public static void main(String[] args)

这个大家都不陌生,main方法接收一个String数组,在反射中开始时我写的是mainmethod.invoke(p, new String[]{"xiaoysec"});//argument type mismatch提示参数匹配的错误

解决的方法是这样的

1 mainmethod.invoke(p, (Object) new String[] { "xiaoysec" });

//或者 mainmethod.invoke(p,new Object[]{new String[]{"xiaoysec"}});

为什么呢?

大致可以这样理解 ,当遇到数组类型的参数时 会进行拆分,例如str[0],str[1]...并将拆分后的参数作为方法的实参这样的话就匹配不到合适的参数了当然反射也就失败了

而方法一(Object) 就是故意的转型让方法认为传入的不是数组

方法二 大致的意思就是 经过拆分后获取到第一个String数组作为方法的实参 这样就符合了main方法接收一个String数组作为实参的条件

下面再来看看反射和泛型的基情:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.xiaoysec.reflecttest;2

3 importjava.lang.reflect.InvocationTargetException;4 importjava.lang.reflect.Method;5 importjava.util.ArrayList;6 importjava.util.Iterator;7

8 importorg.junit.Test;9

10

11

12 public classReflecttest {13 @Test14 public voidtest() {15 ArrayList list = new ArrayList();16 list.add("xiaoysec");17 list.add("B12040423");18 Iterator it =list.iterator();19 while(it.hasNext()) {20 String str =(String) it.next();21 if (str.equals("xiaoysec")) {22 str = "xiaoy";23 //list.add("nanjing"); 在iterator作用范围内不能改变集合中的元素

24 }25 System.out.println(str);26 }27

28 }29 /**

30 * 下面的測試方法證明了java中的泛型只是针对编译时有效31 * 通过反射可以绕过泛型的限制32 */

33 @Test34 public voidtest2() {35 ArrayList list2 = new ArrayList();36 list2.add("XIAOYSEC");37 list2.add("12040423");38 for(String str:list2){39 System.out.println(str);40 }41 System.out.println("-----------------");42 try{43 Class c =list2.getClass();44 Method m = c.getMethod("add", Object.class); //public boolean add(E e)

45 m.invoke(list2, 12); //传入的参数是12 int类型而非String类型

46 Iterator it =list2.iterator();47 while(it.hasNext()) {48 System.out.println(it.next());49 }50 } catch(Exception e) {51 //TODO Auto-generated catch block

52 e.printStackTrace();53 }54

55

56 }57

58 }

View Code

可以看到通过反射可以绕过泛型的限制,也就是说Java泛型是在编译阶段起作用在运行时不会产生限制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值