Java反射机制
Java反射机制出现的原因:
情景1:有些时候,我们不会立即得到我们所需要的类,这个类可能在我们编写完代码之后才会出现,但是我们又知道关于这些类的方法等信息。
情景2:有些时候,我们拥有多个类,这些类都有相同的方法,当我们想去调试这些类的方法的时候,需要重复写多个代码。
比如我们有Person、Dog、Cat类,这些类都有eat方法,我们需要调用Person.eat()、Dog.eat()、Cat.eat()去测试。
当我们知道了反射以后我们就能在一定程度上解决这些问题。
通过反射,我们能够用class文件对象去调用其成员变量,成员方法,构造方法。
首先我们怎么得到class文件对象呢?
1.调用对象的getClass()方法
2.数据类型的静态属性class(.class方法)
3.Class类中的静态方法
public static Class forName(String className)
// 方式1 Person p = new Person(); Class c = p.getClass(); // 方式2 Class c3 = Person.class;// 方式3 Class c4 = Class.forName("ForName");
“ForName”中的字符串是你想调用的类的完整路径名。如:java.lang.Thread。
得到了class对象之后,我们又怎么调用其成员变量,成员方法,构造方法呢?
下面的调用都使用该Person类:
public class Person { private String name; int age; public String address; public Person() { } private Person(String name) { this.name = name; } Person(String name, int age) { this.name = name; this.age = age; } public void eat(String name, int age, String address) { System.out.println(name + "--" + age + "--" + address); } }
1. 调用无参的构造方法(Class.forName实现,构造方法用Constructor接收,用getConstructor()方法获取,用newInstance()创建实例):
public class ReflectDemo { public static void main(String[] args) throws Exception { //得到class对象 Class c = Class.forName("a.b.Person"); //通过class对象过去构造方法对象(con) Constructor con = c.getConstructor(); //创建一个构造方法实例 Object obj = con.newInstance(); //显示 System.out.println(obj); } }
调用带参的构造方法(Class.forName实现,构造方法用Constructor接收,用getConstructor()方法获取,用newInstance()创建实例):
public class ReflectDemo2 { public static void main(String[] args) throws Exception { // 获取字节码文件对象 Class c = Class.forName("a.b.Person"); // 获取带参构造方法对象 // public Constructor<T> getConstructor(Class<?>... parameterTypes) Constructor con = c.getConstructor(String.class, int.class, String.class); // 通过带参构造方法对象创建对象 // public T newInstance(Object... initargs) Object obj = con.newInstance("name", 0, "address"); System.out.println(obj); } }
2.获取成员变量(成员变量用Field接收, 用getField()获取,set方法赋值)
public class ReflectDemo { public static void main(String[] args) throws Exception { // 获得class文件对象 Class c = Class.forName("a.b.Person"); // 得到对象的构造方法 Constructor con = c.getConstructor(); // 将构造方法实例化,相当于实例化一个Person类,即此时的obj是一个Person类。 Object obj = con.newInstance(); // 获取类中的name成员变量 Field addressField = c.getField("name"); // 将obj的name成员变量赋值为Jack addressField.set(obj, "Jack"); // 显示 System.out.println(obj); } }
3.获取成员方法(成员方法用Method接收, 用getMethod()方法获取,用invoke方法赋值):
public class ReflectDemo { public static void main(String[] args) throws Exception { // 获取class文件对象 Class c = Class.forName("a.b.Person"); // 获取构造方法并实例化 Constructor con = c.getConstructor(); Object obj = con.newInstance(); // 得到成员方法 Method m1 = c.getMethod("eat"); // 调用obj的ShowPerson方法 m1.invoke(obj); } }
通过上面的例子,我们知道了一种可以不用先创建一个类就可以直接调用其成员变量,成员方法,构造方法的方式(用Class文件对象去调用其成员变量,成员方法,构造方法)。这样我们就可以解决开始时说的情景1的问题。而且我们只需要修改Class.forNAme方法中的字符串,就可以调用不同类的相同方法了,解决了情景2的问题(比如把调用Person的eat方法改为Dog的eat方法,只需将a.b.Person改为a.b.Dog即可)。

浙公网安备 33010602011771号