反射机制入门

一、什么是反射机制?

  Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,

可以了解任意一个对象所属的类,

可以了解任意一个类的成员变量和方法,

可以调用任意一个对象的属性和方法。

这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

二、获取Class类型对象的三种方式

public static void main(String[] args) {
    Class c1 = null;
    try {
        //第一种方式:Class.forName("完整类名");
        c1 = Class.forName("java.lang.String");
        Class c2 = Class.forName("java.util.Date");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    //第二种方式:类名.class
    Class c3 = java.lang.String.class;
    /**
     * 第三种方式:
     *  先创建对象,拿到对象的引用
     *  调用对象的getClass方法拿到Class对象
     */
    String s = new String();
    Class c4 = s.getClass();
    System.out.println(c1 == c3);//true
    System.out.println(c3 == c4);//true,说明两个对象的内存地址是一样的
}

三、反射获取属性Filed

User类:

class User {
    private String name;
    private Integer age;
    private String sex;
}

反射获取User对象:

public static void main(String[] args) throws Exception {
    Class<?> demo = Class.forName("User");
    Object obj = demo.newInstance();
    // 获取这个对象
    Class<?> objClass = obj.getClass();
    // 获取到所有的属性
    Field[] fields = objClass.getDeclaredFields();
    for (Field field : fields) {
        // 获取修饰符
        int i = field.getModifiers();
        String modifier = Modifier.toString(i);
        // 获取属性类型
        Class<?> type = field.getType();
        String simpleName = type.getSimpleName();
        // 获取属性名
        String fieldName = field.getName();
        System.out.println(modifier + " " + simpleName + " " + fieldName);
    }
}

输出结果:

private String name
private Integer age
private String sex

设置类中某个具体属性的属性值:  

public static void main(String[] args) throws Exception {
    Class user = Class.forName("User");
    // 获取这个属性
    Field name = user.getDeclaredField("name");
    Field age = user.getDeclaredField("age");
    // 获取要修改的对象
    Object obj = user.newInstance();
    // 开启属性的私有访问权限
    name.setAccessible(true);
    age.setAccessible(true);
    // 设置值
    name.set(obj, "lisi");
    age.set(obj, 24);
    // 打印
    System.out.println(name.get(obj));
    System.out.println(age.get(obj));
}

输出结果:

lisi
24

四、反射获取方法

测试类:

class MethodDemo {
    public void m1() {

    }

    public static int m2(int i) {
        return i;
    }
}

反射获取类中的方法:  

public static void main(String[] args) throws Exception {
    // 获取类
    Class<?> methodDemo = Class.forName("MethodDemo");
    // 获取到所有的方法
    Method[] methods = methodDemo.getDeclaredMethods();
    for (Method method : methods) {
        // 获取方法修饰符
        String modifier = Modifier.toString(method.getModifiers());
        System.out.print(modifier + " ");
        Class<?> returnType = method.getReturnType();
        // 获取方法返回值类型
        String returnTypeSimpleName = returnType.getSimpleName();
        System.out.print(returnTypeSimpleName + " ");
        // 获取方法的方法名
        String methodName = method.getName();
        System.out.print(methodName + " ( ) {\n}\n");
        // 获取方法的形参参数列表
        Class<?>[] parameterTypes = method.getParameterTypes();
        for (Class<?> parameterType : parameterTypes) {
            // 获取到的是每一个形参的类型
            String simpleName = parameterType.getSimpleName();
            System.out.println(simpleName);
        }
    }
}

结果:

反射获取某个类的某个特定方法: 

import java.lang.reflect.Method;

/**
 * @author zhangzhixi
 * @date 2021-5-5 9:35
 */
public class Test04_获取类的某个方法 {
    public static void main(String[] args) throws Exception {
        // 1.获取这个类
        Class<?> methodDemo = Class.forName("ObtainMethodDemo");

        // 2.要想通过反射执行方法,得先创建这个对象
        Object obj = methodDemo.newInstance();

        // 3.获取某个类的某个特定方法
        Method m2 = methodDemo.getMethod("m2", int.class);
        Method m1 = methodDemo.getMethod("m1", null);

        // 4.执行方法,传入参数
        m1.invoke(obj, null);
        Object invoke = m2.invoke(obj, 666);
        System.out.println("返回值是:" + invoke);
    }
}

class ObtainMethodDemo {
    public void m1() {
        System.out.println("m1方法执行==>hello");
    }

    public static int m2(int i) {
        return i;
    }
}

测试结果:

m1方法执行==>hello
返回值是:666

反射获取类的构造方法:

import java.lang.reflect.Constructor;

/**
 * @author zhangzhixi
 * @date 2021-5-5 9:49
 */
public class Test05_获取某个类的某个构造方法 {
    public static void main(String[] args) throws Exception {
        // 1.获取class对象
        Class<?> student = Class.forName("Student");
        // 2.获取特定的构造方法
        Constructor<?> constructor = student.getDeclaredConstructor(String.class, Integer.class);
        Constructor<?> studentConstructor = student.getConstructor();
        // 3.执行构造
        studentConstructor.newInstance();
        Object newInstance = constructor.newInstance("张三", 23);
        System.out.println(newInstance);
    }
}

class Student {
    private String name;
    private Integer age;

    public Student() {
        System.out.println("student的无参构造方法执行!");
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试结果:

student的无参构造方法执行!
Student{name='张三', age=23}

反射获取父类/父接口

import java.lang.reflect.AnnotatedType;

/**
 * @author zhangzhixi
 * @date 2021-5-5 10:03
 */
public class Test06_获取类的父类_父接口 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("java.lang.String");

        // 获取父类
        Class<?> superclass = aClass.getSuperclass();
        System.out.println(superclass);

        System.out.println("===============");
        // 获取父接口
        Class<?>[] interfaces = aClass.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface);
        }
    }
}

测试结果:

class java.lang.Object
===============
interface java.io.Serializable
interface java.lang.Comparable
interface java.lang.CharSequence

  

  

  

  

 

  

  

  

posted @ 2021-05-04 22:30  Java小白的搬砖路  阅读(93)  评论(0编辑  收藏  举报