反射获得构造方法创建对象

本篇文章将分为两部分:

1、通过反射获取类的构造方法

获取某一个类中的所有的构造器,通常分为两个步骤:

①明确操作的是哪一份字节码对象

②获取构造器

Class类获取构造器方法:

Constructor类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器

public Constructor<?>[] getConstructors():该方法只能获取当前Class所表示类的public修饰的构造器

public Constructor<?>[] getDeclaredConstructors():获取当前Class所表示类的所有的构造器,和访问权限无关

public Constructor<T> getConstructor(Class<?>... parameterTypes):获取当前Class所表示类中指定的一个public的构造器

参数:parameterTypes表示:构造器参数的Class类型

如:

public User(String name) Constructor c = clz.getCOnstructor(String.class);

public Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):获取当前Class所表示类中指定的一个的构造器,和访问权限无关


class User {
public User() {}
public User(String name) {}
private User(String name, int age) {}
}
public class ConstructorDemo {
public static void main(String[] args) throws Exception {
    //1、先找到被调用构造器所在类的字节码
    Class<User> clz = User.class;
    //2、获取所有构造器
    Constructor<?>[] cs = clz.getConstructors();
    for (Constructor<?> constructor : cs) {
        System.out.println(constructor);
    }
    System.out.println("---------------------------");
    //2、获取指定公有带参数构造器(获取指定公有构造器)
    Constructor<?> c = clz.getConstructor(String.class);
    System.out.println(c);
    System.out.println("---------------------------");
    //获取指定公有无参数构造器(获取指定公有构造器)
    c = clz.getConstructor();
    System.out.println(c);
    System.out.println("---------------------------");
    //2、获取指定私有构造器
    c = clz.getDeclaredConstructor(String.class,int.class);
    System.out.println(c);
}
}

当我们在代码中添加如下代码:


c = clz.getDeclaredConstructor(int.class);

System.out.println(c);

表示:在User中没有找到带有int类型的构造器

2、创建对象

调用构造器,创建对象:

Constructor<T>类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器

常用方法:

public T newInstance(Object...initargs):如调用带参数的构造器,只能使用该方式.

参数:initargs:表示调用构造器的可变实际参数

返回:返回创建的实例,T表示Class所表示类的类型

如果:一个类中的构造器可以直接访问,同时没有参数.,那么可以直接使用Class类中的newInstance方法创建对象.

public Object newInstance():相当于new 类名();

class User {
public User() {
    System.out.println("User()");
}
public User(String name) {
    System.out.println("User(String name)   " + "name = "+name);
}
private User(String name, int age) {
    System.out.println("User(String name, int age)   " + "name = "+name+"  age = "+age);
}
}
public class ConstructorDemo {
public static void main(String[] args) throws Exception {
    //1、先找到被调用构造器所在类的字节码
    Class<User> clz = User.class;
    //2、获取指定公有带参数构造器(获取指定公有构造器)
    Constructor<?> c = clz.getConstructor(String.class); //
    //3、实例化对象
    c.newInstance("huangweiyong");
    System.out.println("---------------------------");
    //获取指定公有无参数构造器(获取指定公有构造器)
    c = clz.getConstructor();
    //3、实例化对象
    c.newInstance();
    System.out.println("---------------------------");
    //直接调用Class类的newInstance方法构造对象
    //3、实例化对象
    clz.newInstance();
    System.out.println("---------------------------");
    //、获取指定私有构造器
    c = clz.getDeclaredConstructor(String.class,int.class);
    //设置私用方法的可访问(切记,这里必须设置,否则会抛出下图的异常)
    c.setAccessible(true);
    //3、实例化对象
    c.newInstance("huangweiyong",18);
}
}

c.setAccessible(true);如果上述代码在调用私有构造函数时没有设置成true或者不写,会抛出异常:
上述异常的原因是:不能够访问User类中一个修饰符为private的成员.

为了安全性考虑,private成员外界不准访问.

但是问题是,我偏要访问:此时就要告诉成员在运行期间忽略掉该安全检查.

解决方案:调用AccessibleObject类中的

publicvoid setAccessible(boolean flag)方法:设置是否可访问

setAccessible(true):可访问的

又因为ConstructorAccessibleObject子类,所以Constructor中具有该方法.

(这一点千万不要忘记,切记切记!!!!!!)

作者:老勇
链接:https://www.jianshu.com/p/60e622123c7c
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容