JAVA 反射机制

来源:互联网 发布:aix 安装软件 编辑:程序博客网 时间:2024/06/05 17:18
     反射机制是java中底层的动态工作机制,是java的核心特性。     静态:经过java编译器的处理以后就固定下来执行顺序,也就是在编译的过程中就已经确定了的,称为静态     动态:java程序在运行期间,才能确定的处理顺序,称为动态发射API的作用:    1 动态加载类    2 动态获取类的信息(类型,属性,方法,构造器等)    3 动态创建对象    4 动态访问属性    5 动态访问方法  动态的加载类并且获取类的信息:    在运行期间动态的加载给定的类到内存方法区。    在动态加载类时要使用类全限定名(类全限定名:包名.类名),我们使用Class类中的一个静态方法动态加载给定的类,这个方法是forName(类全限定名),这个方法的返回值是Class类型的对象,可以通过这个对象访问方法区中类的信息。    Class 在Java中代表类型,任何类型都是Class类型的对象,Class类型的对象在java运行期间是唯一的,并且按需加载。    将一个类加载到内存中,我们把它看做一个对象,那么这个对象就是属于Class类型的对象。    这里我们先写一个普通类Student.Java 用于测试java反射机制。
public class Student {public String name;public String gender;public int age;public Student() {name = "Tom";gender = "f";age = 45;}public Student(String name, String gender, int age) {this.name = name;this.gender = gender;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn name+","+gender+","+age;}}
 


 

@Testpublic void testClassLoader(){try {Class cls=Class.forName("com.xu.test.Student");//获取类名String classType=cls.getName();System.out.println(classType);//result:com.xu.test.Student//动态获取类中的属性的声明,Field是反射包中的类型,代表属性的信息Field[] fields=cls.getDeclaredFields();for(Field field:fields){/*result: * class java.lang.reflect.Field name * class java.lang.reflect.Field gender * class java.lang.reflect.Field age */System.out.println(field.getClass()+" "+field.getName());}//动态获取声明方法中的信息//Method类型的对象描述了方法的信息Method []methods=cls.getDeclaredMethods();for(Method method:methods){//获取方法参数列表//Class就是代表类型的,类型列表就是Class类型的数组Class [] param=method.getParameterTypes();/* * result: * class java.lang.String getName([]) * void setName([class java.lang.String]) * class java.lang.String getGender([]) * void setGender([class java.lang.String]) * int getAge([]) * void setAge([int]) */System.out.println(method.getReturnType()+" "+method.getName()+"("+Arrays.toString(param)+")");}//动态获取构造方法的信息Constructor []constructors=cls.getDeclaredConstructors();for(Constructor constructor:constructors){Class [] param=constructor.getParameterTypes();/* * result: * com.xu.test.Student [] * com.xu.test.Student [class java.lang.String, class java.lang.String, int] */System.out.println(constructor.getName()+" "+Arrays.toString(param));}} catch (ClassNotFoundException e) {//如果没有找该类的话就抛出此异常e.printStackTrace();}}

 

/** * 有三种获取类型Class的方式: *    1 Class.forName(类全限定名)动态根据类名获取类型 *    2 类型.class静态已知类型情况下获取类型,用于已知类型获取类的信息 *    3 对象.getClass()获取对象的类型 *///@Testpublic void testClass(){try {Class cls=Class.forName("com.xu.test.Student");Class cls1=Student.class;System.out.println(cls==cls1);//result:true 说明两个对象是一个对象Class classType=int.class;System.out.println(classType);//intStudent s=new Student();cls=s.getClass();System.out.println(cls);//class com.xu.test.Student} catch (ClassNotFoundException e) {e.printStackTrace();}}


/** * 有三种获取类型Class的方式: *    1 Class.forName(类全限定名)动态根据类名获取类型 *    2 类型.class静态已知类型情况下获取类型,用于已知类型获取类的信息 *    3 对象.getClass()获取对象的类型 *///@Testpublic void testClass(){try {Class cls=Class.forName("com.xu.test.Student");Class cls1=Student.class;System.out.println(cls==cls1);//result:true 说明两个对象是一个对象Class classType=int.class;System.out.println(classType);//intStudent s=new Student();cls=s.getClass();System.out.println(cls);//class com.xu.test.Student} catch (ClassNotFoundException e) {e.printStackTrace();}}

 Class类型经常用于加载包中资源
    包中资源:将软件需要用到的只读资源 图片 文件 音乐,经常被打包到包中
    Java提供了2种包中资源的读取方式:
        1  使用Class类上定义的方法getResource(包路径)是非静态方法必须使用对象调用。

        bin
      |--se
         |-- reflect
         |     |-- demo.txt
         |     |-- TestCase.class
         |-- net
               |-- img.png
       
        包路径:绝对路径,从包的根开始/se/reflect/demo.txt
                相对路径: demo.txt 表示此文件与当前Class类型在一个包中
         (注:此处的路径是以java的包为路径,不是操作系统文件路径!) 
         getResource(路径)返回值是URL类型的对象 ,在URL类型中有openStream()方法,可以返回流对象inputStream。getResourceAsStream()是 getResource与openStream的合体。

@Testpublic void testgetResource() throws IOException{Class cls=this.getClass();URL txt=cls.getResource("demo.txt");InputStream in=txt.openStream();in.close();ClassLoader loader = cls.getClassLoader();URL img = loader.getResource("se/net/img.png");in= img.openStream();System.out.println(in);in.close();}

 2  ClassLoader是Java类的加载器,将一个类读取到方法区中,就是ClassLoader的功劳。ClassLoader中也定义了getResource(路径)方法用于加载资源,路径也是包路径,是一种绝对路径但是不能写“/” 如:se/reflect/demo.txt

    动态创建对象:
       1 使用无参数构造器创建对象,Class类提供的便捷方法newInstance方法。如果没有无参构造器抛出异常。
       2 使用有参数构造器创建对象
           先找到构造器,再调用构造器,并且传递参数调用构造器创建对象

@Testpublic void testConstructor(){try {Class cls=Class.forName("com.xu.test.Student");Object obj=cls.newInstance();System.out.println(obj); //事先知道构造器的参数列表//Class [] types={String.class,String.class,int.class};//Object[] params={"Jerry","f",23};//获得指定参数列表的构造器//Constructor constructor=cls.getConstructor(types);Constructor constructor=cls.getConstructor(String.class,String.class,int.class);//执行构造方法//obj=constructor.newInstance(params);obj=constructor.newInstance("Jerry","f",23);System.out.println(obj);} catch (InstantiationException e) {//没有无参构造器异常e.printStackTrace();} catch (IllegalAccessException e) {//没有访问权限异常e.printStackTrace();} catch (ClassNotFoundException e) {//没有找到类异常e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (IllegalArgumentException e) {//参数错误异常e.printStackTrace();} catch (InvocationTargetException e) {//方法执行异常,获取真正抛出异常的原因Throwable x=e.getCause();x.printStackTrace();//e.printStackTrace();}}//动态访问对象的属性//@Testpublic void testField(){try {String fieldName="name";Class cls = Class.forName("com.xu.test.Student");Object obj=cls.newInstance();//反射API在类上找到属性信息Field field=cls.getField(fieldName);//在对象上获得属性的值Object name=field.get(obj);System.out.println(name);field.set(obj, "Jerry");name=field.get(obj);System.out.println(name);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchFieldException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Testpublic void testMethod(){try {Class cls=Class.forName("com.xu.test.Student");//从类中获取方法的信息Method method=cls.getMethod("getGender");Object obj=cls.newInstance();//在对象上执行方法,obj在执行方法期间传递给了this变量System.out.println(method.invoke(obj));} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}}




 

0 0
原创粉丝点击