Java的反射

1.反射的定义

Java反射是Java被视为动态(或准动态)语言的一个关键性质。JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

2.反射的作用

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;
  • 生成动态代理

3.反射的使用

在运行时创建新类对象在使用Java的反射功能时,首先都要获取类的Class对象,再通过Class对象进行下一步的操作

首先创建一个类作为例子

public class User {
    public Integer userid;
    private String username;
    private String sex;

    public User() {
    }

    public User(Integer userid, String username, String sex) {
        this.userid = userid;
        this.username = username;
        this.sex = sex;
    }

    public User(Integer userid, String username) {
        this.userid = userid;
        this.username = username;
    }

    public Integer getUserid() {
        return userid;
    }

    public String getUsername() {
        return username;
    }

    public String getSex() {
        return sex;
    }

    public void setUserid(Integer userid) {
        this.userid = userid;
    }

    public void setUsername(String username) {
        this.username = username;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "userid=" + userid +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }

    public int method1() {
        System.out.println("这是无参方法1");
        return 0;
    }

    public int method2(Integer n) {
        System.out.println("这是有参方法2,传入参数为:" + n);
        return 0;
    }

    private int method3() {
        System.out.println("这是私有方法3");
        return 0;
    }
}

1)获取Class对象的三种方式

// 一:通过全限定名获取类对象
Class userClass = Class.forName("User");
System.out.println(userClass);
 
// 二:通过类直接获取类对象
Class userClass1 = User.class;
System.out.println(userClass1);
 
// 三:通过类实例获取对象
User user = new User();
Class userClass2 = user.getClass();
System.out.println(userClass2);
System.out.println(userClass.equals(userClass1));
System.out.println(userClass1.equals(userClass2));

运行结果:
Java的反射_第1张图片

2) Class对象的api

Class api: https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html

常用的api有一下几个:

getName():获得类的完整名字。

getFields():获得类的public类型的属性。

getDeclaredFields():获得类的所有属性。包括private 声明的和继承类

getMethods():获得类的public类型的方法。

getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类

getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。

getConstructors():获得类的public类型的构造方法。

getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。

newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

2.1 ) getDeclaredFields() 和 getField()方法的区别

/**
 * getDeclaredFields() 和  getField()方法的区别
 */
Field [] fields =  userClass.getFields();
Field [] declaredFields =  userClass.getDeclaredFields();
 
for(Field item : fields) {
    System.out.println("fields ---> " + item.getName());
}
 
for(Field item : declaredFields) {
    System.out.println("Declared --- >" + item.getName());
}

运行结果:

Java的反射_第2张图片

getField()只能获取公共属性,getDeclaredFields() 可以获取所有属性

2.2)newInstance的使用

		//无参构造方法
        User userParam1 = (User) userClass.newInstance();

        System.out.println("----userid--" + userParam1.getUserid());
        System.out.println("----username--" + userParam1.getUsername());
        System.out.println("----usersex--" + userParam1.getSex());

        //有参构造方法
        Constructor constructor = userClass.getConstructor(Integer.class,String.class);
        User userParam = (User) constructor.newInstance(12,"zhangsan");

        System.out.println("----userid--" + userParam.getUserid());
        System.out.println("----username--" + userParam.getUsername());
        System.out.println("----usersex--" + userParam.getSex());

运行结果:

Java的反射_第3张图片

newInstance()如上面描述的通过无参构造来获取实例化对象,如果想调用有参构造来实例化对象按照上面代码中有参构造方法的调用方法(即先创建有参构造器):

2.3)方法获取与调用

		//无参方法调用
        Method method1 = userClass.getMethod("method1",new Class []{});
        method1.invoke(constructor.newInstance(12,"zhangsan"),new Object[]{});


        //有参方法调用
        Method method2 = userClass.getMethod("method2",Integer.class);
        method2.invoke(userClass.newInstance(),18);

运行结果:
Java的反射_第4张图片

如上代码,getMethod方法中有两个参数,第一个参数为方法名,第二个参数为一个长度可变的参数,它的含义是此方法的多个参数按顺序排列的类对象,假设你的方法为xxxGet(Integer x,String y,Double z),那么你的第二个参数的传参形式为:Integer.class,String.class,Double.calss或者直接使用一个数组new Object[]{Integer.class,String.class,Double.calss},然后真正的调用为invoke()方法,此方法也有两个参数,第一个参数为方法所在的类的实例,第二个为长度可变的参数,他和上面的参数类型相互呼应,以xxxGet(Integer x,String y,Double z)为例,第二个参数你可以写成2,“Roman”,3或者new Object[]{2,“Roman”,3};

2.4)getMethod()和getDeclaredMethods()的区别

getMethod()获取自身能用所有的public公共方法。1.类本身的public 2.继承父类的public 3.实现接口的public;getDeclaredMethod()获取类自身声明的所有方法,包含public、protected和private方法。

/**
         * getMethod() 和 getDeclaredMethods()的区别
         *
         */
        Method [] methods = userClass.getMethods();
        for(Method item : methods){
            System.out.println("--method-- " + item.getName());
        }
        Method [] methodsDec = userClass.getDeclaredMethods();
        for(Method item : methodsDec){
            System.out.println("--methodDec-- " + item.getName());
        }

运行结果:
Java的反射_第5张图片
Java的反射_第6张图片

可以看到
1.getMethod()并没有获取到私有方法method3
2.getMethod()获取到了父类的公共方法,因此比getDeclaredMethod()要多

你可能感兴趣的:(java后端,java,jvm,开发语言)