JAVA学习Java学习笔记Java学习笔记

通过反射获取类的构造方法并且创建对象

2016-09-22  本文已影响900人  老勇

本篇文章将分为两部分:
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所表示类中指定的一个的构造器,和访问权限无关
<pre><code>
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);
}

}
</pre></code>当我们在代码中添加如下代码:
<pre><code>
c = clz.getDeclaredConstructor(int.class);

System.out.println(c);

</pre></code> 表示:在User中没有找到带有int类型的构造器

2、创建对象
调用构造器,创建对象:
Constructor<T>类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器
常用方法:
public T newInstance(Object...initargs):如调用带参数的构造器,只能使用该方式.
参数:initargs:表示调用构造器的可变实际参数
返回:返回创建的实例,T表示Class所表示类的类型

如果:一个类中的构造器可以直接访问,同时没有参数.,那么可以直接使用Class类中的newInstance方法创建对象.
public Object newInstance():相当于new 类名();<pre><code>
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);
}

}</pre></code>c.setAccessible(true);如果上述代码在调用私有构造函数时没有设置成true或者不写,会抛出下图异常:

上述异常的原因是:不能够访问User类中一个修饰符为private的成员.
为了安全性考虑,private成员外界不准访问.
但是问题是,我偏要访问:此时就要告诉成员在运行期间忽略掉该安全检查.
解决方案:调用AccessibleObject类中的
publicvoid setAccessible(boolean flag)方法:设置是否可访问
setAccessible(true):可访问的
又因为ConstructorAccessibleObject子类,所以Constructor中具有该方法.
(这一点千万不要忘记,切记切记!!!!!!)
上一篇下一篇

猜你喜欢

热点阅读