java之反射详解

java之反射详解

反射概述

所谓反射,就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能就叫做java的反射机制。

反射的使用条件是必须先得到代表字节码的Class类。

当我们new一个类时,java就会加载这个类的.class文件,也就是jvm会在本地磁盘中查找.class文件,并加载到jvm的内存中,在这个过程的同时会产生一个Class对象。这个Class对象是jvm自动创建的,并且一个类只产生一个Class对象。

反射的本质就是得到Class对象后,反向获取类的各种信息。

如何获取Class对象

1.通过对象的.getClass()方法获取2.通过静态的class属性3.通过Class类的静态方法:forName(String className)具体代码如下:

    ·//通过getClass方法获得Class对象(都有UserInfo对象,再去获得其Class对象,画蛇添足,没有什么用)
        UserInfo userInfo = new UserInfo();
        Class clz = userInfo.getClass();
        //通过类的class属性
        Class clz1 = UserInfo.class;
        //通过Class类的forName()方法,这种方式最常用
        Class clz2 = Class.forName("suanfa.Reflction.UserInfo");

通过Class对象获得类和对象的属性和方法

本文使用的UserInfo对象的代码如下:

public class UserInfo implements User{
    private int id;
    public String userName;
    private String password;
​
    public int getId(){
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
​
    public String getUserName() {
        return userName;
    }
​
    public void setUserName(String userName) {
        this.userName = userName;
    }
​
    public String getPassword() {
        return password;
    }
​
    public void setPassword(String password) {
        this.password = password;
    }
    public String toString(){
        return "[ID: "+this.id+" name: "+this.userName+" password: "+this.password+"]";
    }
​
    public String toString1(){
        return "[ name: "+ this.userName+" password: "+this.password;
    }
​
    public UserInfo(){}
    public UserInfo(int id,String userName,String password){
        this.password = password;
        this.userName = userName;
        this.id = id;
    }
    private UserInfo(int id,String password){
        this.id = id;
        this.password = password;
    }
​
    @Override
    public void playGame() {
        System.out.println(gameName);
    }
}

其中包含各种属性和方法。

下面,我们将通过Class类来得到它的构造方法:

        //获取所有公有构造方法并打印
        Constructor[] constructor = clz2.getConstructors();
        for (Constructor constructor1 : constructor) {
            System.out.println(constructor1);
        }
        //获取所有的构造方法(包括:私有、受保护、默认、公有)并打印
        Constructor[] clz2DeclaredConstructors = clz2.getDeclaredConstructors();
        for (Constructor c : clz2DeclaredConstructors) {
            System.out.println(c);
        }
        //获取获取公有、无参的构造方法
        final Constructor constructor1 = clz2.getConstructor(null);
        System.out.println(constructor1);
        //通过获取公有、无参构造方法实例该类
        Object object = constructor1.newInstance();
        UserInfo userInfo1 = (UserInfo) object;
        userInfo1.setId(2);
        userInfo1.setUserName("Yun");
        userInfo1.setPassword("123456");
        System.out.println(userInfo1);

对于多个参数的构造方法,在newInstance()中加上相应的参数即可。

通过Class类得到它的属性和方法:

        //获取所有公有的字段并打印
        Field[] fields = clz2.getFields();
        for (Field field : fields){
            System.out.println(field);
        }
        //获取所有的字段(包括私有、受保护、默认的)并打印
        Field[] declaredFields = clz2.getDeclaredFields();
        for (Field field:declaredFields){
            System.out.println(field);
        }
        //获取特定的公有字段并调用(方法一)
        Field userName = clz2.getField("userName");
        System.out.println(userName);
​
        Object o = clz2.getConstructor().newInstance();
        userName.set(o,"xia");
        UserInfo o1 = (UserInfo) o;
        System.out.println("验证姓名: "+o1.getUserName());
        //获取特定的公有字段并调用(方法二)
        Method setUserName = clz2.getMethod("setUserName", String.class);
        setUserName.invoke(o,"Wan");
        System.out.println("验证姓名: "+o1.getUserName());
        System.out.println();
        //获取私有字段并调用
          Field password = clz2.getDeclaredField("password");
        System.out.println(password);
        password.setAccessible(true); //暴力反射,解除私有限制
        password.set(o,"121312");
        System.out.println("验证密码: "+ o1.getPassword());
        
        Method setPassword = clz2.getMethod("setPassword", String.class);
        setPassword.invoke(o,"131452");
        System.out.println("验证密码: "+ o1.getPassword());
        
        //获取所有的”公有“方法
        Method[] methods = clz2.getMethods();
        for (Method m : methods){
            System.out.println(m);
        }

反射的一般流程是通过forName()方法获得Class类,在通过Class类得到它的属性和方法,并加以调用,从而达到无须new该类,便能使用该类。

猜你喜欢

转载自blog.csdn.net/qq_38180223/article/details/81564815