本篇文章将分为两部分:
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)
:可访问的
又因为Constructor
是AccessibleObject
子类,所以Constructor
中具有该方法.
(这一点千万不要忘记,切记切记!!!!!!)
作者:老勇
链接:https://www.jianshu.com/p/60e622123c7c
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。