zoukankan      html  css  js  c++  java
  • Java反射(3)调用方法

    目录:
    1.访问方法(Method)对象的方法汇总
    2.获取方法(Method)对象中的值
    3.设置方法(Method)对象中的值

    1.访问Method的方法汇总

    以下四种方法在Class类可以返回关于字段的 Method 对象。

    Method getMethod(name, Class...):获取某个public的Method(包括父类)
    Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
    Method[] getMethods():获取所有public的Method(包括父类)
    Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
    

    使用示例:

    public class Main {
        public static void main(String[] args) throws Exception {
            Class stdClass = Student.class;
            // 获取public方法getScore,参数为String:
            System.out.println(stdClass.getMethod("getScore", String.class));
            // 获取继承的public方法getName,无参数:
            System.out.println(stdClass.getMethod("getName"));
            // 获取private方法getGrade,参数为int:
            System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
        }
    }
    
    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 Student.getScore(java.lang.String)
    public java.lang.String Person.getName()
    private int Student.getGrade(int)
    

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

    • getName():返回方法名称,例如:"getScore";
    • getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;
    • getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};
    • getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。

    2.调用public的非静态方法

    import java.lang.reflect.Method;
    
    public class MethodMain {
        public static void main(String[] args) throws Exception {
            //1.采用传统方法访问substring()方法
            String str1 = "Hello world1";
            String res1 = str1.substring(6); // "world1"
            System.out.println(res1);
    
            // 2.采用反射访问substring()方法
            String str2 = "Hello world2";
            // 获取public String substring(int beginIndex) 方法,参数为int类型:
            Method method = String.class.getMethod("substring", int.class);//这里需要传入int.class即参数的Class类
            // 在s对象上调用该方法并获取结果:
            String res2 = (String) method.invoke(str2, 6);//invoke(Object obj, Object... args)
            // 打印调用结果:
            System.out.println(res2);//"world2"
        }
    }
    

    注意到substring()有两个重载方法,我们获取的是String substring(int)这个方法。

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

    3.调用非public的非静态方法

    public class Main {
        public static void main(String[] args) throws Exception {
            Person p = new Person();
            Method m = p.getClass().getDeclaredMethod("setName", String.class);
            m.setAccessible(true);//访问非public方法,需要在这里设置一下,否则会报错IllegalAccessException
            m.invoke(p, "Bob");
            System.out.println(p.name);
        }
    }
    
    class Person {
        String name;
        private void setName(String name) {
            this.name = name;
        }
    }
    

    4.访问静态方法

    public class Main {
        public static void main(String[] args) throws Exception {
            // 获取Integer.parseInt(String)方法,参数为String:
            Method m = Integer.class.getMethod("parseInt", String.class);
            // 调用该静态方法并获取结果:
            Integer n = (Integer) m.invoke(null, "12345");//如果获取到的Method表示一个静态方法,调用静态方法时,由于无需指定实例对象,所以invoke方法传入的第一个参数永远为null。我们以Integer.parseInt(String)为例:
            // 打印调用结果:
            System.out.println(n);
        }
    }
    

    5.多态方法的调用

    假设:一个Person类定义了hello()方法,并且它的子类Student也覆写了hello()方法,那么,从Person.class获取的Method,作用于Student实例时,调用的方法到底是哪个?

    public class Main {
        public static void main(String[] args) throws Exception {
            // 获取Person的hello方法:
            Method h = Person.class.getMethod("hello");
            // 对Student实例调用hello方法:
            h.invoke(new Student());//输出:Student:hello 
        }
    }
    
    class Person {
        public void hello() {
            System.out.println("Person:hello");
        }
    }
    
    class Student extends Person {
        public void hello() {
            System.out.println("Student:hello");
        }
    }
    

    运行上述代码,发现打印出的是Student:hello,因此,使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方法(如果存在)。
    反射代码:

    Method m = Person.class.getMethod("hello");
    m.invoke(new Student());
    

    相当于:

    Person p = new Student();
    p.hello();//多态
    

    参考:
    https://www.liaoxuefeng.com/wiki/1252599548343744/1264803678201760

  • 相关阅读:
    Windows 科研软件推荐
    有关Python 包 (package) 的基本知识
    《Using Python to Access Web Data》Week4 Programs that Surf the Web 课堂笔记
    Coursera助学金申请模板
    《Using Databases with Python》 Week2 Basic Structured Query Language 课堂笔记
    Jupyter 解决单个变量输出问题
    解决 pandas 中打印 DataFrame 行列显示不全的问题
    《Using Python to Access Web Data》 Week3 Networks and Sockets 课堂笔记
    缓存击穿及解决方案
    jvm垃圾收集器
  • 原文地址:https://www.cnblogs.com/JohnTeslaaa/p/12716847.html
Copyright © 2011-2022 走看看