反射有性能损失,损失在哪里?
反射的执行过程:
ClassLoader加载一个类会把类信息加载到JVM中,反射方法时,会动态解析Class需要获取方法中的数据组成Method对象,反射执行的时候会通过Method对象执行需要执行的方法
整个过程会产生额外的对象,并且在执行方法时(Method.invoke),每次执行都会检查方法的可见性,相当于用Method对象作为中间者来执行,这种方式比直接执行慢。
反射是基于程序集和元数据的,在使用反射的时候,会搜索元数据,而元数据是基于字符串的,并且无法预编译,所以这一系列操作对性能有影响
Method.invoke方法会对参数做装箱拆箱操作,invoke方法的参数是Object可变长参数,如果方法参数是基本数据类型的话,需要在此装箱,成为基本类型的包装类型,会产生额外对象,在native方法中,需要把包装类拆箱成为基本类型。当调用次数达到一定量的时候,还会触发GC。
Method.invoke代码
@CallerSensitive
// Android-changed: invoke(Object, Object...) implemented natively.
@FastNative
public native Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
其实简单少量的反射并不会对应用性能有太大影响,可以忽略不计,反射大概比直接调用慢50~100倍,但是需要你在执行100万遍的时候才会有所感觉,如果只是偶尔调用一下反射,请忘记反射带来的性能影响。
可以参考这篇文章:反射是否真的会让你的程序性能降低?
Class.getDeclaredMethod与Class.getMethod方法的区别是什么?
getDeclaredMethod(String name, Class<?>… parameterTypes)
获取当前类中的成员方法,不管是否是public,不包括父类继承的方法
getMethod(String name, Class<?>… parameterTypes)
获取public的成员方法,包括从父类继承的方法
getDeclaredField(String name)
用于获取当前类中的变量,不管是否是public,不包括父类继承的方法
getField(String name)
用于获取public的成员变量,包括从父类继承的成员变量
附上
getMethod、getDeclaredMethod源码
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
return getMethod(name, parameterTypes, true);//true:递归获取父类public方法
}
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
return getMethod(name, parameterTypes, false);
}
private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
throws NoSuchMethodException {
if (name == null) {
throw new NullPointerException("name == null");
}
if (parameterTypes == null) {
parameterTypes = EmptyArray.CLASS;
}
for (Class<?> c : parameterTypes) {
if (c == null) {
throw new NoSuchMethodException("parameter type is null");
}
}
//getPublicMethodRecursive获取public的成员方法,包括从父类继承的方法
//getDeclaredMethodInternal获取当前类中的成员方法,不管是否是public,不包括父类继承的方法
Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
: getDeclaredMethodInternal(name, parameterTypes);
// Fail if we didn't find the method or it was expected to be public.
if (result == null ||
//检查方法的可见性
(recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
}
return result;
}
//由getMethod方法调用,获取public的成员方法,包括从父类继承的方法
private Method getPublicMethodRecursive(String name, Class<?>[] parameterTypes) {
// search superclasses
for (Class<?> c = this; c != null; c = c.getSuperclass()) {
Method result = c.getDeclaredMethodInternal(name, parameterTypes);
if (result != null && Modifier.isPublic(result.getAccessFlags())) {
return result;
}
}
return findInterfaceMethod(name, parameterTypes);
}
getDeclaredField源码
/**
* Returns a {@code Field} object that reflects the specified declared
* field of the class or interface represented by this {@code Class}
* object. The {@code name} parameter is a {@code String} that specifies
* the simple name of the desired field.
*/
@FastNative
public native Field getDeclaredField(String name) throws NoSuchFieldException;
getDeclaredFields 源码
/**
* Returns an array of {@code Field} objects reflecting all the fields
* declared by the class or interface represented by this
* {@code Class} object. This includes public, protected, default
* (package) access, and private fields, but excludes inherited fields.
* 返回public、protected,default access和private字段,但是不包括继承的字段
*/
@FastNative
public native Field[] getDeclaredFields();
getField 源码
/**
* Returns a {@code Field} object that reflects the specified public member
* field of the class or interface represented by this {@code Class}
* object. The {@code name} parameter is a {@code String} specifying the
* simple name of the desired field.
*/
public Field getField(String name)
throws NoSuchFieldException {
if (name == null) {
throw new NullPointerException("name == null");
}
Field result = getPublicFieldRecursive(name);
if (result == null) {
throw new NoSuchFieldException(name);
}
return result;
}
/**
* The native implementation of the {@code getField} method.
*
* @throws NullPointerException
* if name is null.
* @see #getField(String)
*/
@FastNative
private native Field getPublicFieldRecursive(String name);
getFields()源码
@CallerSensitive
public Field[] getFields() throws SecurityException {
List<Field> fields = new ArrayList<Field>();
getPublicFieldsRecursive(fields);
return fields.toArray(new Field[fields.size()]);
}
/**
* Populates {@code result} with public fields defined by this class, its
* superclasses, and all implemented interfaces.
*/
private void getPublicFieldsRecursive(List<Field> result) {
// search superclasses
for (Class<?> c = this; c != null; c = c.superClass) {
Collections.addAll(result, c.getPublicDeclaredFields());
}
// search iftable which has a flattened and uniqued list of interfaces
Object[] iftable = ifTable;
if (iftable != null) {
for (int i = 0; i < iftable.length; i += 2) {
Collections.addAll(result, ((Class<?>) iftable[i]).getPublicDeclaredFields());
}
}
}