12.1 反射的概念
12.1.1 反射机制
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。简单的说反射就是动态获取类中信息,对类进行解刨。
理解反射首先要明确一个概念:那就是动态语言!因为我在学习时对“动态获取类中信息”很困惑。
动态语言:程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。
从这个观点出发Java语言不是动态语言,所以Java有了一个非常突出的动态相关机制--Reflection,可以在运行时加载,探知,使用编译时期完全未知的classes,也就是说Java可以加载一个运行时才知道名称的class。也就是说Java反射机制是在运行状态中,对于任意一个类(class文件<字节码文件>),都能知道这个类的属性和方法。对于任意一个对象,都能调用它的属性和方法。这种动态获取类的信息以及动态调用对象的方法的功能成为Java语言的反射机制。简单的说:反射就是把Java类中的各种成分映射成相应的java类。
12.1.2 反射的好处:
反射极大的增强了程序的扩展性。
12.1.3 反射是使用步骤
步骤:
1,获得Class对象,就是获得指定名称的字节码文件对象。
2,实例化对象,获类的属性,方法和构造函数。
3,调用构造函数创建对象,访问属性,调用方法。
12.2 Class类
1字节码
当源程序中用到类时,首先要从硬盘把这个类的那些二进制代码,一个类编译成class文件放在硬盘上以后,就是一些二进制代码,要把这些二进制代码加载到内存中里面来,再用这些字节码去复制出一个一个对象来。
2 Class类的由来
所有的类文件都有共同属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就叫Class(描述字节码文件的对象)。Class类中包含属性有field(字段)、method(方法)、construction(构造函数)。要想对一个类进行内容的获取,必须要先获取该字节码文件的对象。该对象是Class类型。Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等。每一个字节码就是class的实例对象。如:classcls=Data.class;
3 Class和class的区别
1)class:Java中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。
2)Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。例如人对应的是Person类,Java类对应的就是Class。Class是Java程序中各个Java类的总称;它是反射的基石,通过Class类来使用反射。
4 获取Class对象的三种方式
加载XX.class文件进内存时就被封装成了对象,该对象就是字节码文件对象
1).通过对象的getClass方法进行获取。
如:Class clazz=new Person().getClass();//Person是一个类名
弊端:每次都需要具体的类和该类的对象,以及调用getClass方法。
2).任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应 Class对象。
如:Class clazz=Person.class;//Person是一个类名
弊端:还是要使用具体的类,和该类中的一个静态属性class完成。
3). 这种方式较为简单,只要知道类的名称即可。不需要使用该类,也不需要去调用具 体的属性和行为。就可以获取到Class对象了。
如:String className=”Person”;
Class clazz=Class.forName(className);//Person是一个类名
这种方式仅知道类名就可以获取到该类字节码对象的方式,利于扩展。
package reflect; public class Person { private String name; private int age; private String address; public Person() { super(); // TODO Auto-generated constructor stub } public Person(String name, int age, String address) { super(); this.name = name; this.age = age; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
package reflect; /* * 反射: 通过class文件的对象,获取构造函数、字段、方法的操作 * * 学习反射的目的: * 有些时候,可能JDK中的方法没有在帮助文档中提供,但是通过查看源代码,却发现有这个方法,不会该方法为private私有,所以JDK的帮助文档没有提供该方法 * 如果,必须要用这个方法, 我们可以通过反射的方式来获取,进行使用 * * 构造函数: Constructor * 字段:Field * 方法:Method * * * 如何获取Person类的 字节码文件对象呢? * 方式1: getClass(): 返回进行时的类 * 方式2: 数据类型.class 静态属性,来获取当前数据类型的字节码文件对象 * 方式3: public static Class forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象 * */ public class ReflectDemo { public static void main(String[] args) { //反射机制获取当前正在运行的类 // getClassTest1(); //反射机制获取当前正在运行类的字节码文件 getClassTest2(); getClassTest3(); } //通过反射机制,获取当前正在运行的类的字节码文件的对象 //方式一:对象.getClass() public static void getClassTest1(){ Person p1 = new Person(); Person p2 = new Person(); Class c1 = p1.getClass(); Class c2 = p2.getClass(); if (p1==p2) { System.out.println("判断获取到的四个对象之间是否为一个对象:"+"p1和p2是一个对象,地址和内容都一致;"); } else { System.out.println("判断获取到的四个对象之间是否为一个对象:"+"p1和p2不是一个对象,地址或内容不一致;"); } if (c1==c2) { System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2是一个对象,地址和内容都一致;"); } else { System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2不是一个对象,地址或内容不一致;"); } } //通过反射机制,获取当前正在运行的类的字节码文件的对象 //方式一:类名.class 静态属性,来获取当前数据类型的字节码文件对象 public static void getClassTest2(){ Class c1 = Person.class; Class c2 = Person.class; if(c1==c2){ System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2是一个对象,地址和内容都一致;"); }else { System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2不是一个对象,地址或内容不一致;"); } } // 方式3: public static Class forName(String className) // 返回与带有给定字符串名的类或接口相关联的 Class 对象 // className : 类的全路径名称 包名.类名 public static void getClassTest3(){ try { //注意如果不写全路径名,会出现ClassNotFound异常 Class c1 = Class.forName("reflect.Person"); Class c2 = Class.forName("reflect.Person"); if(c1==c2){ System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2是一个对象,地址和内容都一致;"); System.out.println(c1); }else { System.out.println("判断获取到的四个对象之间是否为一个对象:"+"c1和c2不是一个对象,地址或内容不一致;"); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
12.3 常用方法
12.3.1 获取构造函数
package reflect; public class Student { public String name; public int age; private String address; public Student() { super(); // TODO Auto-generated constructor stub } public Student(String name, int age) { super(); this.name = name; this.age = age; } public Student(String name, String address) { super(); this.name = name; this.address = address; } //私有的构造函数 private Student(String name, int age, String address) { super(); this.name = name; this.age = age; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
package reflect; import java.lang.reflect.Constructor; /* * 反射: * * Class类中的方法: * 构造函数: Constructor * public Constructor getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 * public Constructor[] getConstructors() : 获取所有的公共的构造函数 * public Constructor[] getDeclaredConstructors(): 获取所有的构造函数 */ public class ReflectConstructorDemo { public static void main(String[] args) { //根据参数类型获取指定公共构造函数 getConstructorTest(); //获取所有的公共构造函数 getConstrnctorsTest(); //获取指定的构造函数(公有,私有) getDeclaredConstructorTest(); //获取所有的公共构造函数(公有,私有) getDeclaredConstructorsTest(); } //获取指定的公共构造函数 public static void getConstructorTest(){ Class c = Student.class; try { Constructor conPub = c.getConstructor(String.class,int.class); System.out.println(conPub); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } //获取指定的私有构造函数,注意只能获取公共的构造函数,访问私有会报出java.lang.NoSuchMethodException: reflect.Student.<init>(java.lang.String, int, java.lang.String) // try { // Constructor conPri = c.getConstructor(new Class[] {String.class,int.class,String.class}); // System.out.println(conPri); // } catch (NoSuchMethodException | SecurityException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } //获取所有的公共构造函数 public static void getConstrnctorsTest(){ Class c = Student.class; Constructor[] conPub = c.getConstructors(); for (Constructor constructor : conPub) { System.out.println("获取到的所有的公共的构造函数:"+constructor); } } //获取指定的构造函数(公共和私有都可以获取) public static void getDeclaredConstructorTest(){ Class c = Student.class; try { Constructor conPub = c.getDeclaredConstructor(new Class[]{String.class,int.class}); System.out.println("获取公共的构造函数:"+conPub); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class); System.out.println("获取私有的构造函数:"+conPri); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取所有的构造函数(公共和私有都可以获取) public static void getDeclaredConstructorsTest(){ Class c = Student.class; Constructor[] con = c.getDeclaredConstructors(); for (Constructor constructor : con) { System.out.println("获取所有的公共构造函数:"+constructor); } } }
12.3.2 获取当前字节码实例
package reflect; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /* * public Constructor getConstructor(Class<?>... parameterTypes) * * 通过构造函数, 创建对象 * public Object newInstance(Object... initargs) * 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例 */ public class NewInstanceByConstructorDemo { public static void main(String[] args) { //通过构造函数创建实例对象 getPublicInstanceByConstructorTest(); //暴力进入,通过私有构造获取实例 setAccessibleTest(); } //通过构造函数创建实例对象,注意不能创建私有的构造函数,否则报出错误 //java.lang.IllegalAccessException: Class reflect.NewInstanceByConstructorDemo can not access a member of class reflect.Student with modifiers "private" public static void getPublicInstanceByConstructorTest(){ Class c = Student.class; // try { // //创建私有对象 // Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class); // Object obj1 = conPri.newInstance("静",27,"河南"); // Object obj2 = conPri.newInstance("静",27,"河南"); // if (obj1 == obj2) { // System.out.println("获取到的两个对象是同一个地址!"); // }else { // System.out.println("获取到的不是两个对象!"); // } // } catch (NoSuchMethodException | SecurityException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (InstantiationException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (IllegalAccessException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (InvocationTargetException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } //创建公共构造函数 try { Constructor conPub = c.getConstructor(String.class,int.class); Object obj1 = conPub.newInstance("静",27); Object obj2 = conPub.newInstance("静",27); if (obj1==obj2) { System.out.println("创建是同一个对象"); } else { System.out.println("不是同一个对象"); } } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //在上边我们看到私有构造函数创建实例时,报错了,这是java的机制决定的,那么有没有办法让他创建成功呢 /* * 获取Student类中的非public的构造函数,并创建对象 * * public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) * 获取指定的构造函数 (包含私有的) * * public void setAccessible(boolean flag) * 将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查 * * 步骤: * 创建一个Class字节码文件对象 * 获取指定的构造函数 如果是非public的构造函数,需要 强制访问(暴力访问) * 创建对象 */ public static void setAccessibleTest(){ Class c = Student.class; try { Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class); //强制访问,暴力进入,(通过私有构造函数获取对象) conPri.setAccessible(true); Object obj = conPri.newInstance("静",27,"河南"); System.out.println(obj); Object object = conPri.newInstance("静",27,"河南"); System.out.println(object); } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
12.3.3 获取当前字节码中字段
package reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; /* * 字段:Field * * private String name; * int age; * public String address; * * 步骤: * a: 创建class字节码文件对象 * b: 获取指定的字段,如果是非public 修饰的字段, 需要 暴力访问 * c: 对字段进行操作 * * Class中的方法: * public Field[] getFields() : 获取 public 修饰的 所有字段 * public Field[] getDeclaredFields(): 获取所有的字段(包含私有) * public Field getDeclaredField(String name):获取指定的字段,包含私有 * public Field getField(String name): 获取指定的字段 * * Field中的方法: * public void set(Object obj, Object value): 为指定对象中的当前字段, 赋值 Person p1; Person p2; addressField.set( p1,"上海"); * */ public class ReflectFieldDemo { public static void main(String[] args) { //获取指定的字段(公共的),操作字段 getPubFieldTest(); //获取指定的字段(私有的),操作字段 getPriFieldTest(); //获取所有公共字段 getPubFieldsTest(); //获取所有字段(含私有) getAllFieldsTest(); } //获取指定的字段(公共的) public static void getPubFieldTest(){ //获取字节码对象 Class c = Student.class; //获取指定字段 try { //获取构造函数 Constructor conPub = c.getConstructor(String.class,int.class); //获取实例对象 Object obj = conPub.newInstance("静",27); //获取指定字段 Field fN = c.getField("name"); //设置对象字段 fN.set(obj, "静"); Field fA = c.getField("age"); fA.set(obj, 27); System.out.println(obj); Student stu = (Student) obj; System.out.println(stu.getName()+"--"+stu.getAge()); System.out.println("-------------------------------------"); } catch (NoSuchFieldException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取指定的字段(私有的) public static void getPriFieldTest(){ Class c = Student.class; try { //获取私有的构造函数 Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class); //暴力获取实例 conPri.setAccessible(true); Object obj = conPri.newInstance("静",25,"河北"); //获取字段 Field fN = c.getDeclaredField("name"); Field fA = c.getDeclaredField("age"); fA.set(obj, 27); Field fAdder = c.getDeclaredField("address"); //java.lang.IllegalAccessException: Class reflect.ReflectFieldDemo can not access a member of class reflect.Student with modifiers "private" //不能直接操作私有字段,否则报错上面, // fAdder.set(obj, "河南"); fAdder.setAccessible(true); fAdder.set(obj, "河南"); Student stu = (Student) obj; System.out.println(stu.getName()+"--"+stu.getAge()+"--"+stu.getAddress()); System.out.println("-------------------------------------"); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取所有的字段(公共) public static void getPubFieldsTest(){ //获取字节码文件 Class c = Student.class; try { //获取构造函数 Constructor conPub = c.getConstructor(String.class,int.class); Object obj = conPub.newInstance("静",25); //获取所有公共字段 Field[] f = c.getFields(); for (Field field : f) { System.out.println(field.get(obj)); System.out.println(field); System.out.println("-------------------------------------"); } } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取所有字段(含私有) public static void getAllFieldsTest(){ Class c = Student.class; try { Constructor conPri = c.getDeclaredConstructor(String.class,int.class,String.class); conPri.setAccessible(true); Object obj = conPri.newInstance("静",27,"河南"); Field[] f = c.getDeclaredFields(); for (Field field : f) { //字段数组中存在私有,要暴力访问 field.setAccessible(true); System.out.println(field.get(obj)); System.out.println(field); System.out.println("-------------------------------------"); } } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
12.3.4 获取当前字节码中的方法
package reflect; public class Student { public String name; public int age; private String address; public Student() { super(); // TODO Auto-generated constructor stub } public Student(String name, int age) { super(); this.name = name; this.age = age; } public Student(String name, String address) { super(); this.name = name; this.address = address; } //私有的构造函数 private Student(String name, int age, String address) { super(); this.name = name; this.age = age; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } private void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
package reflect; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /* * 反射方法: Method * * 步骤: * a: 创建class 字节码文件对象 * b: 获取指定的方法 * c: 使用方法(需要前有对象,才能使用方法) * * Class类中的方法: * public Method[] getMethods() 获取所有的公共方法(包含父类的) * public Method[] getDeclaredMethods() 获取所有的方法(不包含父类) * * public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法 * name: 想要获取的方法的名字 * parameterTypes: 获取的方法的参数列表的数据类型 * * public Method getDeclaredMethod(String name, Class<?>... parameterTypes) : 获取指定的方法(包含私有的) * * Method类的方法: * public Object invoke(Object obj, Object... args) * 调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了 * 暴力访问 * public void setAccessible(boolean flag) * */ public class ReflectMethodDemo { public static void main(String[] args) { //获取指定方法(公共) getPubMethodTest(); //获取所有的公共方法 getPubMethodsTest(); //获取所有方法,含私有 getAllMethodsTest(); } //获取指定方法(公共),私有 public static void getPubMethodTest(){ //获取字节码文件 Class c = Student.class; //获取构造函数,创建该字节码文件对象实例 try { Constructor conPub = c.getConstructor(String.class,int.class); Object obj = conPub.newInstance("静",27); //获取指定方法,公共 Method m1 = c.getMethod("setName", String.class); //java.lang.NoSuchMethodException: reflect.Student.setAge(int) // Method m2 = c.getMethod("setAge", int.class); //获取指定方法,私有 Method m2 = c.getDeclaredMethod("setAge", int.class); m1.invoke(obj, "岁月静好"); //java.lang.IllegalAccessException: Class reflect.ReflectMethodDemo can not access a member of class reflect.Student with modifiers "private" //暴力调用私有方法 m2.setAccessible(true); m2.invoke(obj, 28); Student stu = (Student) obj; System.out.println(stu.getName()+"--"+stu.getAge()); System.out.println("---------------------------------------"); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取所有的公共方法 public static void getPubMethodsTest(){ Class c = Student.class; try { Constructor con = c.getConstructor(String.class,int.class); Object obj = con.newInstance("静",27); Method[] mm = c.getMethods(); for (Method method : mm) { System.out.println("方法名字:"+method.getName()); } System.out.println("---------------------------------------------"); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取所有的方法(含私有) public static void getAllMethodsTest(){ Class c = Student.class; try { Constructor con = c.getConstructor(); Object obj = c.newInstance(); Method[] mm = c.getDeclaredMethods(); for (Method method : mm) { System.out.println(method.getName()); } } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
12.3.5 通过反射向集合中添加字符串
package reflect; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; /* * 需求: ArrayList<Integer> list = new ArrayList<Integer>(); * 向集合中 添加3个字符串 * * 通过反射来解决该问题 * * 思路: * a: 获取 ArrayList 的字节码文件对象 * b: 获取 add 方法 * c: 使用方法 * * 注意: 当我们的java文件 生成对应的Class文件的时候, 泛型是不会编译到 class文件中的 */ public class ReflectTest { public static void main(String[] args) { //通过反射向集合中添加字符串] test(); } public static void test(){ ArrayList<String> al = new ArrayList<>(); Class c = al.getClass(); try { Method m = c.getMethod("add", Object.class); m.invoke(al, "2014"); m.invoke(al, "2015"); m.invoke(al, "2016"); System.out.println("ArrayList:"+al); } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
12.4 反射的优点和缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。