美文网首页
Constructor类

Constructor类

作者: OakesYa | 来源:发表于2020-05-18 20:18 被阅读0次

    类图

    之前我们用反射创建一个类的对象可以通过该Class.newInstance()方法,但是可以发现这个方法只能构造包含无参构造函数的类,如果不包含则会报NoSuchMethodException异常,那么这个时候就需要用到Constructor类了。我们先看看Constructor类的类关系图


    类图

    源码(精简版)

    public final class Constructor<T> extends Executable {
        //用来存储ConstructorAccessor
        private Constructor<T>      root;
        //通过传入参数构造相对应的实例
        public T newInstance(Object ... initargs)
            throws InstantiationException, IllegalAccessException,
                   IllegalArgumentException, InvocationTargetException
        {
            if (!override) {
                if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                    Class<?> caller = Reflection.getCallerClass();
                    checkAccess(caller, clazz, null, modifiers);
                }
            }
            if ((clazz.getModifiers() & Modifier.ENUM) != 0)
                throw new IllegalArgumentException("Cannot reflectively create enum objects");
            ConstructorAccessor ca = constructorAccessor;   // read volatile
            if (ca == null) {
                ca = acquireConstructorAccessor();
            }
            @SuppressWarnings("unchecked")
            T inst = (T) ca.newInstance(initargs);
            return inst;
        }
        //获取ConstructorAccessor 
        private ConstructorAccessor acquireConstructorAccessor() {
            // First check to see if one has been created yet, and take it
            // if so.
            ConstructorAccessor tmp = null;
            if (root != null) tmp = root.getConstructorAccessor();
            if (tmp != null) {
                constructorAccessor = tmp;
            } else {
                // Otherwise fabricate one and propagate it up to the root
                tmp = reflectionFactory.newConstructorAccessor(this);
                setConstructorAccessor(tmp);
            }
    
            return tmp;
        }
    
        // 直接返回root里的ConstructorAccessor
        ConstructorAccessor getConstructorAccessor() {
            return constructorAccessor;
        }
    
        // 给root赋值
        void setConstructorAccessor(ConstructorAccessor accessor) {
            constructorAccessor = accessor;
            // Propagate up
            if (root != null) {
                root.setConstructorAccessor(accessor);
            }
        }
    }
    

    由于其他方法基本都是复写的父类等,所以这边就只看了newInstance方法,可以通过reflectionFactory.newConstructorAccessor(this);方法获取不同的ConstructorAccessor并调用newInstance创建一个实例

    实例

    public class EmployeeDto {
        private int age;
        private String name;
    
        EmployeeDto() {
            this.age = 0;
            this.name = "default";
        }
    
        EmployeeDto(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public boolean isOlder(int tmpAge) {
            return age > tmpAge;
        }
    
        @Override
        public String toString() {
            return "age:" + age + ",name:" + name;
        }
    }
    
    public class EmployeeConstructorTest {
    
        public static void main(String[] args) {
            try {
                Class clazz = Class.forName("reflect.EmployeeDto");
                Constructor[] constructors = clazz.getDeclaredConstructors();
                for (Constructor constructor : constructors) {
                    if (constructor.getParameterCount() == 2) {
                        constructor.setAccessible(true);
                        EmployeeDto employeeDto = (EmployeeDto) constructor.newInstance(1,"test");
                        System.out.println(employeeDto);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    EmployeeDto类有一个含参构造函数,然后main方法获取到该构造函数并newInstance创建一个实例并打印构建的对象,我们看看执行结果

    Connected to the target VM, address: '127.0.0.1:65499', transport: 'socket'
    age:1,name:test
    Disconnected from the target VM, address: '127.0.0.1:65499', transport: 'socket'
    

    执行没有问题

    相关文章

      网友评论

          本文标题:Constructor类

          本文链接:https://www.haomeiwen.com/subject/xqhpohtx.html