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

  • 相关阅读:
    Sublime Text安装Package Control
    HTTP,FTP,TCP,UDP及SOCKET
    Oracle数据库的导入导出
    C#.NET中数组、ArrayList和List三者的区别
    一道有趣的逻辑面试题(数独)
    C#常用命名空间
    C# Dictionary已知value获取对应的key
    C#记录程序耗时的方法
    有return语句情况下,try-catch-finally的执行顺序
    C# 拷贝数组的几种方法
  • 原文地址:https://www.cnblogs.com/JohnTeslaaa/p/12716847.html
Copyright © 2011-2022 走看看