需求:通过反射来获取某一个类的构造
1.获取该类的字节码对象
2.从该字节码对象中去找需要获取的构造器
Class 类获取构造器方法:
Constructor 类,表示类中构造器的类型,Constructor 的实例就是某一个类中的某一构造器:
获取当前 Class 所表示类的 public 修饰的构造器:
public Constructor<?>[] getConstructors();
获取当前 Class 所表示类的所有的构造器(和访问权限无关):
public Constructor<?>[] getDeclaredConstructors()
获取当前 Class 所表示类中指定一个 public 的构造器:
public Constructor<T> getConstructor(Class<?>... parameterTypes);
参数:parameterTypes 表示:构造器参数的 Class 类型
例如:
public People(String name);
Constructor c = clz.getConstructor(String.class);
构造器的最大作用:创建对象。
问题:
为什么使用反射创建对象,为什么不直接来 new 呢?
解答:
在框架中,提供给我们的都是字符串,此时只能使用反射创建对象。
步骤:
1.找到构造器所在类的字节码对象
2.获取构造器对象
3.使用反射,创建对象
Constructor 类,表示类中构造器的类型,Constructor 的实例就是某一个类中的某一个构造器。
常用方法:
调用带参数的构造器,只能使用该方式:
public T newInstance(Object... initargs);
参数:initargs:表示调用构造器的实际参数
返回:返回创建的实例,T 表示 Class 所表示类的实例
如果一个类中的构造器是外界可以直接访问,同时没有参数,那么可以直接使用 Class 类中的 newInstance 方法创建对象!
public Object newInstance();//相当于new 类名();
访问私有的成员,必须先设置可访问的:
对象.setAccessible(true);
使用反射获取类中的方法:
1:获取方法所在类的字节码对象
2:获取方法
Class 类中常用方法:
获取包括自身和继承过来的所有 public 方法:
public Method[] getMethods();
获取自身类中所有的方法(不包括继承的,且和访问权限无关):
public Method[] getDeclaredMethods();
调用指定的一个公共的方法(包括继承的):
public Method getMethod(String methodaName,Class<?>... parameterTypes);
参数:
methodName:表示被调用方法的名字
parameterTypes:表示被调用方法的参数的 Class 类型。
调用指定的一个本类中的方法(不包括继承的):
public Method getDeclaredMethod(String methodaName,Class<?>... parameterTypes);
参数:
methodName:表示被调用方法的名字
parameterTypes:表示被调用方法的参数的 Class 类型
使用反射调用方法:
1.获取方法所在类的字节码对象
2.获取方法对象
3.使用反射调用方法
调用当前 Method 所表示的方法:
public Object invoke(Object obj,Object...args):
参数:
obj:表示调用方法底层所属对象
Method method = clz.getMethod(Object...args);
args:表示调用方法时传递的实际参数类型
返回:底层方法的返回结果
调用私有方法:
在调用私有方法之前,应该设置该方法为可访问的,
又因为 Method 是 AccessibleObject 子类,所以Method中具有该方法:
method.setAccessible(true);
使用反射调用静态方法:
静态方法不属于任何对象,静态方法属于类本身,
此时把 invoke 方法的第一个参数设置为 null 即可
static public void doSomething(String str){
System.out.println("Person.doSomething()"+name);
}
Method method = clz.getMethod("doSomething",String.class);
method.invoke(null,"Simple");
使用反射调用数组参数(可变参数):
调用方法的时候把实际参数都作为 Object 数组的元素即可
Method 对象.invoke (方法底层所属对象,new Object[]{所有实参})
反射其他的API:
方法名 | 作用 |
int getModifiers() | 获得修饰符 |
String getName() | 返回类的全限定名 |
String getSimpleName() | 获得类的简单名字 |
Package getPackage() | 获得该类的包名 |
Class getSuperClass() | 获得该类的父类 |
boolean isArray() | 判断该 Class 实例是否是数组 |
boolean isEnum() | 判断该 Class 实例是否是枚举 |