反射基础

getDeclaredMethod:获取当前类的所有声明的方法,包括public、protected和private修饰的方法。需要注意的是,这些方法一定实在当前类中声明的,从父类中继承的不算,实现接口的方法由于有声明所以包括在内。

getDeclaredMethod(类方法类型,方法参数),如int就是int.class,String就是String.class,多个参数用“,”隔开。

getMethod:获取当前类和父类的所有public的方法。这里的父类,指的是继承层次中的所有父类。比如说,A继承B,B继承C,那么B和C都属于A的父类。

package com.superman.reflectclass;

import java.awt.dnd.DragGestureEvent;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Students {
    public Students(int age, boolean sex, String name) {
        this.age = age;
        this.sex = sex;
        this.name = name;
    }

    private int age;
    private boolean sex;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Students{" +
                "age=" + age +
                ", sex=" + sex +
                ", name='" + name + '\'' +
                '}';
    }
}
public class Reflecttest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Students stu = new Students(18,true,"luo");
        Class s1 = stu.getClass();
        System.out.println("s1:" + s1);
        Class s2 = Class.forName("com.superman.reflectclass.Students");
        System.out.println("s2:" + s2);
        Class s3 = Students.class;
        System.out.println("s3:" + s3);
        Class s4 = ClassLoader.getSystemClassLoader().loadClass("com.superman.reflectclass.Students");
        System.out.println("s4:" + s4);
        Class name = Class.forName("java.lang.Runtime");

        Method[] DeclaredMethods = name.getDeclaredMethods();
        for (Method m1 : DeclaredMethods)
        System.out.println("获取除继承外的所有方法:" + m1);
        Method[] DeclaredMethods2 = s1.getMethods();
        for (Method m2 : DeclaredMethods2)
        System.out.println("获取所有公共方法:" + m2);
        Method m3 = s1.getMethod("setAge",int.class);
        System.out.println("获取特定方法:" + m3);
        Method m4 = name.getMethod("exec",String.class);
        System.out.println("获取特定方法" + m4);

        Field[] getDeclaredFields = s1.getDeclaredFields();
        for (Field f1:getDeclaredFields)
            System.out.println("获取成员变量不含父类声明字段:" + f1);

    }
}

通过反射调用Runtime执行命令,由于runtime是单例模式,只能通过getRuntime获取当前的Runtime

法一:

 

package com.superman.test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectRuntime1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Class clazz = Class.forName("java.lang.Runtime");
        Method m1 =clazz.getMethod("getRuntime");
        Object obj2 = m1.invoke(clazz);
        Method m2 = clazz.getMethod("exec", String.class);
        Process pro = (Process) m2.invoke(obj2,"calc.exe");
    }
}

 

 

法二:

package com.superman.test;

import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectRuntimetest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
        Class rt = Class.forName("java.lang.Runtime");
        Constructor ct = rt.getDeclaredConstructor();
        ct.setAccessible(true);
        Object obj = ct.newInstance();
        Method mt = rt.getMethod("exec",String.class);
        Process pro = (Process)mt.invoke(obj,"whoami");
        InputStream in = pro.getInputStream();
        System.out.println(IOUtils.toString(in,"GBK"));
    }

}

runtimeClass1.getDeclaredConstructor和runtimeClass1.getConstructor都可以获取到类构造方法,区别在于后者无法获取到私有方法,所以一般在获取某个类的构造方法时候我们会使用前者去获取构造方法。如果构造方法有一个或多个参数的情况下我们应该在获取构造方法时候传入对应的参数类型数组,如:clazz.getDeclaredConstructor(String.class, String.class)。

反射调用方法:

获取到java.lang.reflect.Method对象以后我们可以通过Method的invoke方法来调用类方法。

调用类方法代码片段:

method.invoke(方法实例对象, 方法参数值,多个参数值用","隔开);

method.invoke的第一个参数必须是类实例对象,如果调用的是static方法那么第一个参数值可以传null,因为在java中调用静态方法是不需要有类实例的,因为可以直接类名.方法名(参数)的方式调用。

method.invoke的第二个参数不是必须的,如果当前调用的方法没有参数,那么第二个参数可以不传,如果有参数那么就必须严格的依次传入对应的参数类型。

posted @ 2021-10-22 15:56  我要变超人  阅读(34)  评论(0编辑  收藏  举报