目前流行的 Perl、Python、Ruby 等都是动态语言,所谓动态是指在程序运行期间可以改变程序结构和变量类型。Java 并不具备这点,所以Java不是动态语言。不过,尽管 Java 不是动态语言,但利用它的 Reflection(反射)机制同样可以在程序运行期间得到 Class 的名称,构造并生成其实例。利用 Reflection 我们可以为 fields(属性)赋值,调用其 method。
在《Java反射(一)》一文中,我们简单了解了利用 Reflection 机制在程序运行期间生成 Class 实例,今天我们仍然简单地了解一下,利用 Reflection 机制为动态调用 method。
Class 对象的 getMethod 方法可以返回该 Class 表示的类(包括父类或接口)所声明的所有公共方法的 Method 数组。它有一个重载方法 getMethod(String name, Class… parameterTypes),该方法返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。name 参数是一个 String,用于指定方法名。parameterTypes 参数是按声明顺序标识该方法参数类型的 Class 对象的一个数组。如果 parameterTypes 为 null,则按空数组处理。
- import java.lang.reflect.Method;
- public class User {
- /** 用户ID */
- private String id;
- /** 用户名 */
- public String name;
- public void setId(String id) {
- this.id = id;
- }
- public String getId() {
- return this.id;
- }
- public static void main(String[] args) {
- Method[] methods = User.class.getMethods();
- for (Method method : methods) {
- System.out.println(method.getName());
- }
- }
- }
运行上面的程序,控制台 User 及父类 Object 中的所有方法名称:
setId
main
getId
hashCode
getClass
wait
wait
wait
equals
toString
notify
notifyAll
若想要取得某一方法,将 main 方法改为如下:
- public static void main(String[] args) {
- try {
- Method me = User.class.getMethod("getId", new Class [] {});
- System.out.println(me.getName());
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
若取得的方法需要参数,只要将参数类型传入即可:
- Method me = User.class.getMethod("setId", new Class [] {String.class});
很多情况下,方法的参数类型是一个接口,或者是一个类型的父类型,这时若我们传入的参数类型为其子类型时将抛出 NoSuchMethodException 异常。这也很容易理解,Java 允许方法重载,相同名字的方法有可能会有多个,而区分这些方法的条件就是其参数个数和类型。所以如果不使用方法参数的实际类型做为查找条件,取到的方法很有可能是错误的。如下:
- import java.lang.reflect.Method;
- public class Manager extends User {
- private User u;
- public void set(User u) {
- this.u = u;
- }
- public static void main(String[] args) {
- try {
- Method me = Manager.class.getMethod("set", new Class [] {Manager.class});
- System.out.println(me.getName());
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }
Manager 继承了 User,并且声明了一个 User 为参数的 set 方法,这时如果我们的 getMethod 的参数中使用 Manager 做为参数类型,将抛出异常。
java.lang.NoSuchMethodException: Manager.set(Manager)
at java.lang.Class.getMethod(Class.java:1605)
at Manager.main(Manager.java:12)
这时,我们可以改用 User.class 或 Manager.class.getSuperclass() 作为参数。
若方法的参数类型为接口的场合,我们可以利用 Class 的 getInterfaces 方法取得其实现的接口类型。Java 允许实现多个接口,所以 getInterfaces 方法返回一个 Class 的数组。
| 五冠 Nokia/诺基亚 5230 5230XM 送证书V20版 内有港行 销数千台 | ||
| 1000.0元 | ||
| 批发 雷朋3025镜面反光太阳镜 太阳眼镜 19.9/副 顶级质量 | ||
| 19.9元 | ||
| 促销笔记本电脑 13.3英寸超薄N450无线网卡视频 | ||
| 1999.0元 | ![]() | |





