java中的反射机制

xiaoxiao2021-02-28  100

什么是反射:

反射就是把java类中的各种成分映射成一个个的java对象(加载类,然后解刨出类的各个组成部分)。例如,一个类由:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。   反射一般会用在什么地方:相信大家在学习JavaEE的时候用过很多框架,比如,spring框架中的IOC反向控制就是利用反射机制,其实大部分框架都会使用到反射,在举一个就是在设计模式中的动态代理,其实也是使用反射机制实现的。  

反射的使用:

Class类:

在使用反射的一些方法之前相信,让我们先来了解Class这个类。大家在很多代码中都会遇到这个类,那么这个类到底表示的是什么呢?其实Class类是用来表示一个字节码的对象,大家应该都知道一个类从编译成.class文件到类加载器加载到内存的过程。其实Class类就是用来表示一个类在内存中字节码的对象。我们之所以要了解Class这个类,因为我们后面的反射方法都是基于这个类对象的。   如何得到某个class文件的class对象: 类名.class

Class clazz = ArrayList.class

对象.getClass()

Class clazz = new ArrayList().getClass()

Class.forNme("类名")        Class clazz = Class.forName("java.util.ArrayList")  

Constructor类:

Constructor类的实例对象代表类的一个构造函数。

1)如果我们想得到某个类的所有构造方法,例: Constructor [] constructors = Class.forName("java.lang.String").getConstructors(); 2)如果我们想得到某个类的特定构造方法,例: Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class) 3)让你想不到是我们可以利用构造方法创建实例对象: String str = (String)constructor.newInstance("abc"); 4)Class类的newInstance()方法也可以创建类的实例,其内部工作原理就是先得无参构造方法 构造方法,再用构造方法创建实例对象: String obj = (String)Class.forName("java.lang.String").newInstance();  

Field类:

Field类代表某各类中一个成员变量。 这里就有一个问题等着大家,得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联的是哪个对象呢?这里特别解释一下,这里Field对象代表的是变量的定义,而不是具体的变量的值。这里给出Student类的定义: public class Student { public String name = "张三"; private int age; } 1)操作公共变量 public void test1() throws Exception{ Student stu = new Student(); Class clazz = Student.class; Field f = clazz.getField("name");//如果前面说的只是获取的name变量的定义 System.out.println(f.get(stu)); //这一句使用来获取特定的对象也就是stu这个对象的name值 f.set(stu, "李四"); //这一句是给stu这个对象的name赋值 Field f1 = clazz.getField("name"); System.out.println(f1.get(stu)); } 2)操作私有变量 public void test2() throws Exception{ Student stu = new Student(); Class clazz = Student.class; Field f = clazz.getDeclaredField("age");//注意与公共成员变量方法的不同 f.setAccessible(true); //这一句不能少,意义及时获取权限 f.set(stu,18); System.out.println(f.get(stu)); }

Method类

Method这个类代表某个类中的一个成员方法 1)得到类中的某一个方法: eg: Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class); 这里getMethod()的第一个参数表示方法名称,第二个参加表示方法参数。   2)调用方法: 通常方式:System.out.println(str.charAt(1)); 反射方式:System.out.println(charAt.invoke(str,1));  上面的str表示一个String对象。这里如果传递给Method对象的第一个参数为null的话,那么就说明该Method对象对应的是一个静态方法。   3)注意JDK1.4和JDK1.5的invoke方法的区别 Jdk1.5:public Object invoke(Object obj,Object... args) Jdk1.4:public Object invoke(Object obj,Object[] args), 这里我们用一个例子来说明这个差别及解决办法,假设我们要写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。我们知道启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语解释,因此会出现参数类型不对的问题。解决办法就是 mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});这样我们就能解决上面的问题。
转载请注明原文地址: https://www.6miu.com/read-54016.html

最新回复(0)