您的位置:首页 > 编程语言 > Java开发

Java初级培训笔记------反射

2015-08-18 19:41 323 查看
什么是反射:反射就是通过.class文件将该class文件封装为一个类(Class)的对象剖析.java文件,在被编译后,运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性的一个动态调用和动态获取的行为,但是反射也只能是获取或者是调用该类中的属性和方法,并不能对该类进行修改,对源文件并没有影响。注意两点:一个是运行时一个是不修改源文件属性。这样做的意义何在呢:Java程序能够运行,那么就得让Java类被Java虚拟机加载,那么想调用类中的方法属性,最常用的就是对该类进行对象的创建,然后调用。但是当你创建该类的对象之后,你是可以直接对该类的属性进行修改的,但是有时候考虑到安全性等问题的时候我这个类中的属性是不允许你修改的,比如说我在一个类中存储了几个人的银行账户和银行密码,不能随便修改,为了安全,我可以考虑将构造方法的权限全部设置成私有,这时候你是没有办法new一个新对象的,那么现在要用到里边的信息或者是方法了,又没有办法创建对象,这时候我们就可以通过反射来调用和查看方法属性,但是却不会对该类造成破坏。适用场景:①当需要动态获取某一个类的属性方法时②当不允许对一个类创建新对象或者是该类不允许被修改时③java设计模式中的代理模式,动态代理需要用到反射机制一个类是由两部分组成的一个类名一个类体,类体又包含了三部分属性,方法和构造函数,反射中主要用到了lang包中的4个类,分别是Class(进行类级操作,得到信息等)Constructor(专门用于构造方法)Method(方法级操作,调用等)Field(属性操作,赋值调用等)新建一个学生类(student)有姓名(name) ,性别(sex),年龄(age)三个属性提供set和get方法以及有参和无参的构造方法Class:怎样将class文件封装成Class的对象:三种方法:1.Class c1=Student.class//调用class方法直接把类封装成一个Class对象 返回2.Class  c2=Class.forName(“com.x.y.ClassName”);//调用forName方法通过识别java文件的路径(包括包名类名)直接封装3.Student  s=null;//不创建对象       Class c3=s.getClass;通过class方法生成对象c1.newInstance();//调用c1所表示的类的无参构造函数,所以在类中要记得手动添加无参构造c1.getName();//返回类名Constructor:由Class对象产生Constructor,封装的是一个class文件中的所有的构造方法(将构造方法封装为对象)所以可以对构造方法进行操作访问//使用c1对象,完成对student对应的class文件的剖析,获得c1表示的class文件的所有构造方法Constructor[] cons=c1.getConstructors();//Constructor类的对象封装的是c1表示的class文件所有构造方法,返回一个Constructor数组for(Constructor c:cons){//获得构造方法的详细信息System.out.println(c.getName()+"\t"+c.getModifiers()+"\t"+Arrays.toString(c.getParameterTypes()));//分别表示构造方法名}//获得某个特定的构造方法(Constructor对象),获得指定参数的构造方法,因为构造方法是可以重写的clz2.getConstructor(String.class,String.class);//括号里是参数类型Constructor c1=clz2.getConstructor(new Class[]{String.class,String.class});System.out.println(c1.getName()+"\t"+c1.getModifiers()+"\t"+Arrays.toString(c1.getParameterTypes()));分别是 获得构造方法的名字,获得构造方法的访问修饰符类型  以数组的形式返回构造方法的参数列表Method:
		//创建class对象Class<Student> c=Student.class;//对方法操作//接收类里的所有方法Method[] ms=c.getDeclaredMethods();for (Method m : ms) {System.out.println(m);}//接收指定的方法  因为方法是存在重写的 这时候接收指定的方法的时候需要指明参数或者无餐写nulltry {//无参的Method m=c.getDeclaredMethod("show", null);System.out.println(m);//有参的   参数类型  需要传的值为class类型Method m1=c.getDeclaredMethod("show", int.class,int.class);System.out.println(m1);//得到方法的方法名     访问 修饰符(权限)    返回值类型 和参数列表System.out.println(m1.getName()+"\t"+m1.getModifiers()+"\t"+m1.getReturnType()+"\t"+m1.getParameterAnnotations());<span style="white-space:pre">	</span>//因为m1总共有两个参数  所以参数类型返回的是一个数组//如何通过方法改变属性值    调用类里边的set方法//先创建set方法的method对象Method set1=c.getDeclaredMethod("setName", String.class);Method set2=c.getDeclaredMethod("setAge", int.class);//完成赋值并<span style="color:#ff0000;">调用</span>采用的是Student s=c.newInstance();set1.invoke(s, "张三");//前半部分传的值是student的对象s  后边是赋值属性set2.invoke(s, 19);m1.invoke(s, 1,8);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}
Field:
<strong style="font-size:18px;">		</strong><span style="font-family:KaiTi_GB2312;font-size:12px;">//查看student类里边的所有成员属性Field[] fs=c.getDeclaredFields();//遍历输出for (Field f:fs) {System.out.println(f);}try {//查看student类里边的指定成员Field fc = c.getDeclaredField("name");System.out.println(fc);//因为封装过程总  将属性设置为私有所以要改变访问权限才能访问Student s=c.newInstance();fc.setAccessible(true);//变更访问权限  ,是私有属性可以访问//修改属性fc.set(s, "张三");System.out.println(fc.get(s));//返回指定对象上此 Field 表示的字段的值。fc表示的是nameSystem.out.println(fc.getName()+fc.getType()+fc.getModifiers());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: