转自:https://blog.csdn.net/sinat_38259539/article/details/71799078#commentBox
1.什么是反射?
反射是通过一个类可以知道其中所含的属性和方法,并且对于一个对象可以调用它的任意属性和方法;
这种动态获取信息以及动态调用对象的方法就是JAVA语言的反射机制。
2. 反射就是把JAVA类中的各种成分映射成一个对象。
比如类中有成员变量,方法,构造方法等信息,利用反射技术对一个类进行解剖,把各个组成部分映射成为一个对象!
//因为每个类定义是只有一个的,对象可以实例化很多个,以前的理解还是太粗浅了。
3.重要的Class类
获取Class对象的三种方法:
package fanshe; /** * 获取Class对象的三种方式 * 1 Object ——> getClass(); * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性 * 3 通过Class类的静态方法:forName(String className)(常用) * */ public class Fanshe { public static void main(String[] args) { //第一种方式获取Class对象 Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。 Class stuClass = stu1.getClass();//获取Class对象 System.out.println(stuClass.getName()); //第二种方式获取Class对象 Class stuClass2 = Student.class; System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个 //第三种方式获取Class对象 try { Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名 System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象 } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
1)通过对象的getClass()函数获取
2)通过对象的class属性获取(任何数据类型,包括基本数据类型都有一个静态的class属性)
3)通过Class类的静态方法forName("报名.类名");
在运行期间,一个类只有一个class对象产生。
第三种方法是常用的,可以通过一个字符串来创建对象。
并且给出了一些例子,
例1:
可以反射数据成员、方法、构造函数、并且可以反射main方法:
Student类:
package fanshe.main; public class Student { public static void main(String[] args) {//定义了一个main方法。 System.out.println("main方法执行了。。。"); } }
Main类:
package fanshe.main; import java.lang.reflect.Method; /** * 获取Student类的main方法、不要与当前的main方法搞混了 */ public class Main { public static void main(String[] args) { try { //1、获取Student对象的字节码 Class clazz = Class.forName("fanshe.main.Student"); //2、获取main方法 Method methodMain = clazz.getMethod("main", String[].class);//第一个参数:方法名称,第二个参数:方法形参的类型, //3、调用main方法 // methodMain.invoke(null, new String[]{"a","b","c"}); //第一个参数,对象类型,因为方法是static静态的,所以为null可以,第二个参数是String数组,这里要注意在jdk1.4时是数组,jdk1.5之后是可变参数 //这里拆的时候将 new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。 methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一 // methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二 } catch (Exception e) { e.printStackTrace(); } } }
例2:
可以通过配置文件来定义。
public class Student { public void show(){ System.out.println("is show()"); } }
配置文件pro.txt
className = cn.fanshe.Student
methodName = show
测试类:
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.Method; import java.util.Properties; /* * 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改 * 我们只需要将新类发送给客户端,并修改配置文件即可 */ public class Demo { public static void main(String[] args) throws Exception { //通过反射获取Class对象 Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student" //2获取show()方法 Method m = stuClass.getMethod(getValue("methodName"));//show //3.调用show()方法 m.invoke(stuClass.getConstructor().newInstance()); } //此方法接收一个key,在配置文件中获取相应的value public static String getValue(String key) throws IOException{ Properties pro = new Properties();//获取配置文件的对象 FileReader in = new FileReader("pro.txt");//获取输入流 pro.load(in);//将流加载到配置文件对象中 in.close(); return pro.getProperty(key);//返回根据key获取的value值 } }