反射有性能损失,损失在哪里?Class.getDeclaredMethod与Class.getMethod方法的区别是什么?

本文深入探讨了Java反射机制的性能损失原因,包括Method对象的创建、元数据搜索、方法可见性检查、装箱拆箱操作及GC触发等,对比直接调用的性能差异。同时,解析了Class.getDeclaredMethod与Class.getMethod方法的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射有性能损失,损失在哪里?

反射的执行过程:
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());
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值