【反射】Constructor类

Constructor类中包含了构造方法定义的详细信息,可以使用Constructor类中提供的方法来获取构造方法的信息,下面我们先获取Constructor对象,再介绍如何使用Constructor类中的newInstance方法创建对象。

一、准备工作

在src/test/java目录的cn.horse.reflect.entity包下新建BaseEntity类、UserInfoEntity类

BaseEntity类:

package cn.horse.reflect.entity;

public abstract class BaseEntity {
    public Long id;

    public BaseEntity() { }
    public BaseEntity(Long id) {
        this.id = id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }
}

UserInfoEntity类:

package cn.horse.reflect.entity;

@SuppressWarnings({})
public class UserInfoEntity extends BaseEntity {
    public String name;
    private Integer age;

    private UserInfoEntity() {
    }

    public UserInfoEntity(Long id) {
        super(id);
    }

    public UserInfoEntity(Long id, String name, Integer age) {
        super(id);
        this.name = name;
        this.age = age;
    }


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

    public Integer getAge() {
        return age;
    }

    private String getName() {
        return name;
    }

    private void check() { }
}

二、获取Constructor对象

在src/test/java目录的cn.horse.reflect包下新建GetConstructorInstanceTests测试类

GetConstructorInstanceTests类:

package cn.horse.reflect;

import cn.horse.reflect.entity.UserInfoEntity;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

public class GetConstructorInstanceTests {

    static final Class USER_INFO_ENTITY_CLASS = UserInfoEntity.class;

    @Test
    public void testGetConstructors() {
        // getConstructors 获取当前类中使用public定义的构造方法
        Collection constructorNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getConstructors()).map(Constructor::toString).collect(Collectors.toList());
        List expectedConstructorNameList = Arrays.asList("public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long)", "public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long,java.lang.String,java.lang.Integer)");
        assertThat(constructorNameList.size()).isEqualTo(expectedConstructorNameList.size());
        assertThat(constructorNameList).containsAll(expectedConstructorNameList);
    }

    @Test
    public void testGetConstructor() throws NoSuchMethodException {
        assertThatExceptionOfType(NoSuchMethodException.class).isThrownBy(() -> USER_INFO_ENTITY_CLASS.getConstructor());
        assertThat(USER_INFO_ENTITY_CLASS.getConstructor(Long.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getConstructor(Long.class, String.class, Integer.class)).isNotNull();
    }

    @Test
    public void testGetDeclaredConstructors() {
        // getDeclaredConstructors 获取当前类中定义的所有构造方法
        Collection declaredConstructorNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructors()).map(Constructor::toString).collect(Collectors.toList());
        List expectedDeclaredConstructorNameList = Arrays.asList("private cn.horse.reflect.entity.UserInfoEntity()", "public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long)", "public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long,java.lang.String,java.lang.Integer)");
        assertThat(declaredConstructorNameList.size()).isEqualTo(expectedDeclaredConstructorNameList.size());
        assertThat(declaredConstructorNameList).containsAll(expectedDeclaredConstructorNameList);
    }

    @Test
    public void testGetDeclaredConstructor() throws NoSuchMethodException {
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor()).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class)).isNotNull();
    }
}

单元测试方法介绍:

testGetConstructors使用getConstructors方法获取当前类中使用public定义的构造方法

testGetConstructor使用getConstructor方法获取当前类中使用public定义的指定构造方法(使用构造方法的参数类型进行匹配)

testGetDeclaredConstructors使用getDeclaredConstructors方法获取当前类中定义的所有构造方法

testGetDeclaredConstructor使用getDeclaredConstructor方法获取当前类中定义的指定构造方法(使用构造方法的参数类型进行匹配)

三、Constructor类中方法的使用

在src/test/java目录的cn.horse.reflect包下新建ConstructorInstanceMethodTests测试类

ConstructorInstanceMethodTests类:

package cn.horse.reflect;

import cn.horse.reflect.entity.UserInfoEntity;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

public class ConstructorInstanceMethodTests {

    static final Class USER_INFO_ENTITY_CLASS = UserInfoEntity.class;

    @Test
    public void testGetDeclaringClass() throws NoSuchMethodException {
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getDeclaringClass()).isEqualTo(UserInfoEntity.class);
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getDeclaringClass()).isEqualTo(UserInfoEntity.class);
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getDeclaringClass()).isEqualTo(UserInfoEntity.class);
    }

    @Test
    public void testGetName() throws NoSuchMethodException {
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getName()).isEqualTo("cn.horse.reflect.entity.UserInfoEntity");
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getName()).isEqualTo("cn.horse.reflect.entity.UserInfoEntity");
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getName()).isEqualTo("cn.horse.reflect.entity.UserInfoEntity");
    }

    @Test
    public void testToString() throws NoSuchMethodException {
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().toString()).isEqualTo("private cn.horse.reflect.entity.UserInfoEntity()");
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).toString()).isEqualTo("public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long)");
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).toString()).isEqualTo("public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long,java.lang.String,java.lang.Integer)");
    }

    @Test
    public void testGetModifiers() throws NoSuchMethodException {
        assertThat(Modifier.isPrivate(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getModifiers())).isTrue();
        assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getModifiers())).isTrue();
        assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getModifiers())).isTrue();
    }

    @Test
    public void testNoArgsConstructorCreateInstance() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 获取private定义的无参数的构造方法创建对象
        Constructor noArgsConstructor = USER_INFO_ENTITY_CLASS.getDeclaredConstructor();
        assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() -> noArgsConstructor.newInstance());
        noArgsConstructor.setAccessible(true);
        Object noArgsConstructorInstance = noArgsConstructor.newInstance();
        assertThat(noArgsConstructorInstance).isInstanceOf(USER_INFO_ENTITY_CLASS);
        assertThat(((UserInfoEntity) noArgsConstructorInstance).getId()).isNull();
    }

    @Test
    public void testIdArgsConstructorCreateInstance() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 获取public定义的参数只有id的构造方法创建对象
        Constructor idArgsConstructor = USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class);
        Object idArgsConstructorInstance = idArgsConstructor.newInstance(200L);
        assertThat(idArgsConstructorInstance).isInstanceOf(USER_INFO_ENTITY_CLASS);
        assertThat(((UserInfoEntity) idArgsConstructorInstance).getId()).isEqualTo(200L);
    }

    @Test
    public void testAllArgsConstructorCreateInstance() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 获取public定义的参数包含id,name,age的构造方法创建对象
        Constructor allArgsConstructor = USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class);
        Object allArgsConstructorInstance = allArgsConstructor.newInstance(200L, "张三", 10);
        assertThat(allArgsConstructorInstance).isInstanceOf(USER_INFO_ENTITY_CLASS);
        assertThat(((UserInfoEntity) allArgsConstructorInstance).getId()).isEqualTo(200L);
        assertThat(((UserInfoEntity) allArgsConstructorInstance).name).isEqualTo("张三");
        assertThat(((UserInfoEntity) allArgsConstructorInstance).getAge()).isEqualTo(10);
    }
}

单元测试方法介绍:

testGetDeclaringClass获取声明类的Class对象,getDeclaringClass方法获取到的Class对象是构造方法所在类的Class对象

testGetName获取名称,getName方法获取到的名称是构造方法所在类的名称

testToString转换成字符串,toString方法用于将构造方法对象转换成字符串

testGetModifiers获取修饰符,使用getModifiers获取修饰符,并使用Modifier类提供的静态方法依次判断了是否使用了public、private、protected等修饰符

testNoArgsConstructorCreateInstance使用无参数的构造方法创建对象,方法中首先获取了无参数的构造方法,直接使用newInstance创建对象会抛出IllegalAccessException异常,原因是构造方法使用了private修饰,这里使用setAccessible设置访问了访问全限后在使用newInstance创建对象就可以了

testIdArgsConstructorCreateInstance使用id参数的构造方法创建对象

testAllArgsConstructorCreateInstance使用所有参数的构造方法创建对象

你可能感兴趣的:(#,反射,java,java反射)