Java反射机制总结

什么是反射

反射是程序运行过程中,对于任意一个类,都可以获得这个类的属性和公有方法(公有私有属性方法都可以获得,只不过获得有区别);对于任意一个对象,都可以调用它的属性和方法.

反射的作用

  • 在运行时获得一个对象所属的类(即可以根据这个对象获得这个类的名称,地址等信息,粗浅理解,帮助记忆)
  • 在运行时实例化一个类的对象
  • 在运行时获得和使用一个对象的方法和属性
  • 动态代理

反射的使用

前提:先创建几个类和接口,后面使用:
People.java

public class People {
    private int height;
    private int weight;
    public int test1;
    int test2;
    protected int test3;
    public People() {
        super();
    }

    public People(int height, int weight) {
        super();
        this.height = height;
        this.weight = weight;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

Student.java

public class Student extends People implements StudentInterface1,StudentInterface2{
    private String id="144520";
    private String name="大明";
    private String gender;

    public Student() {
        super();
    }

    public Student(String id, String name, String gender) {
        super();
        this.id = id;
        this.name = name;
        this.gender = gender;
    }
    public Student(String id,String name){
        this.id=id;
        this.name=name;
    }
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", gender=" + gender + "]";
    }

    public String getId() {
        return id;
    }

    public void setId(String id,String name) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public void setPassword() {

    }

    @Override
    public void getPassword() {

    }
}

StudentInterface1.java

public interface StudentInterface1 {
    public void setPassword();
}

StudentInterface2.java

public interface StudentInterface2 {
    public void getPassword();
}

通过一个对象获得完整的包名和类名

  1. 方法一(常用)
  Class c1=Class.forName("com.reflex.Student");
  1. 方法二
Class c1=Student.class;
  1. 方法三
 Student student = new Student();
Class c1 = student.getClass();
System.out.println(c1);

实例化一个对象

Class c = Class.forName("com.reflex.Student");
// 创建一个Class的一个实例
Object o = c.newInstance();// 调用Student的一个无参构造方法
System.out.println(c.getName());

获得对象的父类和实现的接口

        Class c = Class.forName("com.reflex.Student");
        // 获得父类
        Class parentClass = c.getSuperclass();
        System.out.println(parentClass);
        // 获得接口
        Class intf[] = c.getInterfaces();
        for (int i = 0; i < intf.length; i++) {
            System.out.println(intf[i]);
        }

获得构造方法

        Class c = Class.forName("com.reflex.Student");
        // 一、实例化一个无参构造方法,对对象set值
        Student student = (Student) c.newInstance();
        student.setId("144520", "");
        student.setName("小明");
        student.setGender("男");
        // 取Student对象的值
        System.out.println(student.toString());
        // 二、获得全部的构造方法,通过对构造方法传参数来赋值对象的成员变量
        Constructor cons[] = c.getConstructors();
        // 遍历每个构造方法
        for (int i = 0; i < cons.length; i++) {
            System.out.println("第" + (i + 1) + "个构造方法");
            // 获得每个构造方法的参数类型
            Class para[] = cons[i].getParameterTypes();
            for (int j = 0; j < para.length; j++) {
                System.out.println("[" + j + "]" + para[j]);
            }

        }
        // 对三个参数的构造方法进行传参数(此处没有详写,直接传参)
        Student stu = (Student) cons[1].newInstance("1545245", "小花", "test");
        System.out.println(stu.toString());
        //另一种使用构造的方法是
        //查看API有两个方法,分别是getConstructor(Class...)和newInstance(Class...)
        //举例含有2个参数的构造方法
        Student stu1 = c.getConstructor(String.class,String.class).newInstance("001","小明");

获得对象的所有成员变量

        Class c = Class.forName("com.reflex.Student");
        // 一、获得本对象的属性
        System.out.println("获得本对象的属性");
        Field field[] = c.getDeclaredFields();
        for (int i = 0; i < field.length; i++) {
            // 得到权限修饰符
            int modify = field[i].getModifiers();
            String modifyStr = Modifier.toString(modify);
            // 得到属性的类型
            Class type = field[i].getType();
            // 输出这个变量
            System.out.println(modifyStr + " " + type + " " + field[i].getName());
        }
        // 二、获得父类或者接口的公共属性,只有public修饰的才能获得
        System.out.println("获得父类或者接口的公共属性");
        Field paraentField[] = c.getFields();// 这个方法返回的是父类或者接口可以访问的公共属性,私有属性不会返回
        for (int i = 0; i < paraentField.length; i++) {
            // 获得权限修饰符
            int paraentModify = paraentField[i].getModifiers();
            String paraentModifyStr = Modifier.toString(paraentModify);
            // 获得类型
            Class paraentType = paraentField[i].getType();
            System.out.println(paraentModifyStr + " " + paraentType + " " + paraentField[i].getName());
        }

获得对象的所有公共方法

        Class c = Class.forName("com.reflex.Student");
        // 获得所有公共的方法
        Method[] method = c.getMethods();
        for (int i = 0; i < method.length; i++) {
            // 获得方法的修饰符
            int modify = method[i].getModifiers();
            String modifyStr = Modifier.toString(modify);
            // 获得方法的返回类型
            Class returnType = method[i].getReturnType();
            // 获得参数的类型
            Class para[] = method[i].getParameterTypes();
            System.out.print(modifyStr + " " + returnType + " " + method[i].getName() + "( ");
            // 循环遍历参数类型
            for (int j = 0; j < para.length; j++) {
                System.out.print(para[j].getName() + " ");
            }
            System.out.println(")");
        }

通过反射机制调用对象的方法

        Class c = Class.forName("com.reflex.Student");
        // 一、调用对象的方法一
        Method method = c.getMethod("getId");
        Object o = null;
        method.invoke(o = c.newInstance());
        // 测试
        // 获取id的属性
        Field idF = c.getDeclaredField("id");
        // 打破封装
        idF.setAccessible(true);
        System.out.println(idF.get(o));
        // 二、调用对象的方法二
        method = c.getMethod("setId", String.class, String.class);
        method.invoke(c.newInstance(), "123456789", "test");

打破封装,操作对象的属性

        Class c = Class.forName("com.reflex.Student");
        // 获得属性
        Field nameF = c.getDeclaredField("name");
        // 实例化
        Object o = c.newInstance();
        // 打破封装
        nameF.setAccessible(true);
        // 对属性name赋值
        nameF.set(o, "test name");
        System.out.println(nameF.get(o));// 这个地方的取值跟传统方法不同

未完待续,伸个懒腰,先睡一觉:)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值