JAVA反射之调用方法

时间:2025-03-10 19:11:36

参考:JAVA反射之调用方法

java反射前及反射后类的实例化等操作

一、反射 调用方法

1.1 获得 Method 对象

我们已经能通过Class实例获取所有Field对象,同样的,可以通过Class实例获取所有Method信息。Class类提供了以下几个方法来获取Method

  • Method getMethod(name, Class...):获取某个publicMethod(包括父类)

  • Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)

  • Method[] getMethods():获取所有publicMethod(包括父类)

  • Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)

public class Main {
    public static void main(String[] args) throws Exception {
        Class stdClass = ;
        // 获取public方法getScore,参数为String:
        (("getScore", ));
        // 获取继承的public方法getName,无参数:
        (("getName"));
        // 获取private方法getGrade,参数为int:
        (("getGrade", ));
    }
}
 
class Student extends Person {
    public int getScore(String type) {
        return 99;
    }
    private int getGrade(int year) {
        return 1;
    }
}
 
class Person {
    public String getName() {
        return "Person";
    }
}
public int ()
public  ()
private int (int)

Method 对象的信息获取:

一个Method对象包含一个方法的所有信息:

  • getName():返回方法名称,例如:"getScore"

  • getReturnType():返回方法返回值类型,也是一个Class实例,例如:

  • getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{, }

  • getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。

1.2 调用非静态方法

先得到 Method 对象 然后再调用 invoke 方法

当我们获取到一个Method对象时,就可以对它进行调用。我们以下面的代码为例:

String s = "Hello world";
String r = (6); // "world"

如果用反射来调用substring方法,需要以下代码:

// reflection 
import ;
public class Main {
    public static void main(String[] args) throws Exception {
        // String对象:
        String s = "Hello world";
        // 获取String substring(int)方法,参数为int:
        Method m = ("substring", );
        // 在s对象上调用该方法并获取结果:
        String r = (String) (s, 6);
        // 打印调用结果:
        (r);
    }
}

Method实例调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错。

1.3 调用静态方法

如果获取到的Method表示一个静态方法,调用静态方法时,由于无需指定实例对象,所以invoke方法传入的第一个参数永远null。我们以(String)为例:

// reflection import ; 
public class Main {
    public static void main(String[] args) throws Exception {
        // 获取(String)方法,参数为String:
        Method m = ("parseInt", );
        // 调用该静态方法并获取结果:
        Integer n = (Integer) (null, "12345");
        // 打印调用结果:
        (n);
    }
}

1.4 调用非 public 方法

和Field类似,对于非public方法,我们虽然可以通过()获取该方法实例,但直接对其调用将得到一个IllegalAccessException。为了调用非public方法,我们通过(true)允许其调用:仍然可能失败

// reflection
import ;
public class Main {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        Method m = ().getDeclaredMethod("setName", );
        (true);
        (p, "Bob");
        ();
    }
}
 
class Person {
    String name;
    private void setName(String name) {
         = name;
    }
}

1.5 多态

我们来考察这样一种情况:一个Person类定义了hello()方法,并且它的子类Student也覆写了hello()方法,那么,从获取的Method,作用于Student实例时,调用的方法到底是哪个?
使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方法(如果存在)。