mybatis3.4.1源代码 - ReturnType、ResultMap.getType()

14 篇文章 0 订阅

ReturnType == ResultMap.getType()
1、实例类
2、list、map的value值类型

 

package cn.java.demo.ibatis.internal.resolve_return_type;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public interface UserMapper {

    // --- void
    void methodRespVoid();

    // --- entity
    UserEntity methodRespEntity();

    // --- array
    UserEntity[] selectListRespArray();

    // --- List
    List<UserEntity> methodRespList();

    List<List<UserEntity>> methodRespListNest1();

    List<List> methodRespListNest2();

    List<UserEntity[]> methodRespListNestArray();

    List<ArrayList> methodRespListNestArrayList0();

    List<ArrayList<UserEntity>> methodRespListNestArrayList1();

    List<ArrayList<?>> methodRespListNestArrayList2();

    List<ArrayList<? extends UserEntity>> methodRespListNestArrayList3();

    List<byte[]> methodRespListNestArrayList4(); // 无效

    // --- Map
    Map<Long, UserEntity> methodRespMap();

    Map<Long, Map<Long, UserEntity>> methodRespMapNest();

}

测试代码

package cn.java.demo.ibatis.internal.resolve_return_type;

import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
import org.apache.ibatis.reflection.TypeParameterResolver;
import org.apache.ibatis.session.Configuration;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.lang.reflect.*;
import java.util.Collection;
import java.util.Map;

public class Test {

    public static void main(String[] args) throws Exception {
        Class clazz = UserMapper.class;


        if (false) {
            Method method = clazz.getMethod("insertOne");
            parseParams(method);
        }

        if (true) {
            // void
            {
                if (true) {
                    System.out.println("------方法定义 void methodRespVoid() ------");
                    Method method = clazz.getMethod("methodRespVoid");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType); // class cn.java.demo.ibatis.internal.reflection.UserEntity
                    getReturnType(method, clazz);
                }
            }

            // entity
            {
                if (true) {
                    System.out.println("------方法定义 UserEntity methodRespEntity() ------");
                    Method method = clazz.getMethod("methodRespEntity");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType); // class cn.java.demo.ibatis.internal.reflection.UserEntity
                    getReturnType(method, clazz);
                }
            }

            // array
            {
                if (true) {
                    System.out.println("------方法定义 UserEntity[] selectListRespArray() ------");
                    Method method = clazz.getMethod("selectListRespArray");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType); // class cn.java.demo.ibatis.internal.reflection.UserEntity
                    getReturnType(method, clazz);
                }
            }

            // list
            {
                if (true) {
                    System.out.println("------方法定义 List<UserEntity> methodRespList() ------");
                    Method method = clazz.getMethod("methodRespList");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    // ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class cn.java.demo.ibatis.internal.reflection.UserEntity]]
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<List<UserEntity>> methodRespListNest1() ------");
                    Method method = clazz.getMethod("methodRespListNest1");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    // ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class cn.java.demo.ibatis.internal.reflection.UserEntity]]]]
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<List> methodRespListNest2() ------");
                    Method method = clazz.getMethod("methodRespListNest2");
                    // ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[interface java.util.List]]
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<UserEntity[]> methodRespListNestArray() ------");
                    Method method = clazz.getMethod("methodRespListNestArray");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    // ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[interface java.util.List]]
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<ArrayList> methodRespListNestArrayList0() ------");
                    Method method = clazz.getMethod("methodRespListNestArrayList0");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    // ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[interface java.util.List]]
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<ArrayList<UserEntity>> methodRespListNestArrayList1() ------");
                    Method method = clazz.getMethod("methodRespListNestArrayList1");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<ArrayList<?>> methodRespListNestArrayList2() ------");
                    Method method = clazz.getMethod("methodRespListNestArrayList2");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<ArrayList<? extends UserEntity>> methodRespListNestArrayList3() ------");
                    Method method = clazz.getMethod("methodRespListNestArrayList3");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 List<byte[]> methodRespListNestArrayList4() ------");
                    Method method = clazz.getMethod("methodRespListNestArrayList4");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }
            }

            // map
            {
                if (true) {
                    System.out.println("------方法定义 Map<Long,UserEntity> methodRespMap() ------");
                    Method method = clazz.getMethod("methodRespMap");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    // ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null, actualTypeArguments=[class java.lang.Long, class cn.java.demo.ibatis.internal.reflection.UserEntity]]
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }

                if (true) {
                    System.out.println("------方法定义 Map<Long,Map<Long,UserEntity>> methodRespMapNest() ------");
                    Method method = clazz.getMethod("methodRespMapNest");
                    Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, clazz);
                    // ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null, actualTypeArguments=[class java.lang.Long, ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null, actualTypeArguments=[class java.lang.Long, class cn.java.demo.ibatis.internal.reflection.UserEntity]]]]
                    System.out.println(resolvedReturnType);
                    getReturnType(method, clazz);
                }
            }
        }

        if (false) {
            /**
             * @see org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parseResultMap(java.lang.reflect.Method)
             * @see org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#getReturnType(java.lang.reflect.Method)
             */
            Method mapperMethod = clazz.getMethod("selectListRespList");

            Method builderMethod = getReturnTypeMethod(MapperAnnotationBuilder.class, "getReturnType");
            if (builderMethod != null) {
                if (!Modifier.isPublic(builderMethod.getModifiers())) {
                    builderMethod.setAccessible(true);
                }

                Configuration configuration = new Configuration();
                MapperAnnotationBuilder parser = new MapperAnnotationBuilder(configuration, clazz);
                Class<?> returnType = (Class<?>) builderMethod.invoke(parser, mapperMethod);
                System.out.println(returnType); // class cn.java.demo.ibatis.internal.reflection.UserEntity
            }
        }
    }


    /**
     * @param method
     * @param type
     * @see org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#getReturnType(java.lang.reflect.Method)
     */
    private static void getReturnType(Method method, Class type) {
        Class<?> returnType = method.getReturnType();
        Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, type);
        if (resolvedReturnType instanceof Class) { //
            // UserEntity methodRespEntity()
            System.out.println("resolvedReturnType instanceof Class");
            returnType = (Class<?>) resolvedReturnType;
            if (returnType.isArray()) {
                // UserEntity[] selectListRespArray()
                System.out.println("returnType.isArray(),returnType = " + returnType);
                returnType = returnType.getComponentType();
                System.out.println("returnType.getComponentType() = " + returnType); // cn.java.demo.ibatis.internal.reflection.UserEntity
            }

            // gcode issue #508
            if (void.class.equals(returnType)) { // 空返回
                // void methodRespVoid()
                System.out.println("void.class.equals(returnType)");
            }
        } else if (resolvedReturnType instanceof ParameterizedType) {
            System.out.println("resolvedReturnType instanceof ParameterizedType");
            ParameterizedType parameterizedType = (ParameterizedType) resolvedReturnType;
            Class<?> rawType = (Class<?>) parameterizedType.getRawType();
            System.out.println("rawType = " + rawType);
            if (Collection.class.isAssignableFrom(rawType)) { // 集合类型
                System.out.println("Collection.class.isAssignableFrom(rawType)");
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                if (actualTypeArguments != null && actualTypeArguments.length == 1) {
                    Type returnTypeParameter = actualTypeArguments[0]; // 元素的类型
                    System.out.println("returnTypeParameter.getTypeName() = " + returnTypeParameter.getTypeName());
                    if (returnTypeParameter instanceof Class<?>) {
                        // List<UserEntity> methodRespList();
                        // List<List> methodRespListNest2();
                        // List<UserEntity[]> methodRespListNestArray();
                        // List<ArrayList> methodRespListNestArrayList0();
                        System.out.println("returnTypeParameter instanceof Class<?>");
                        returnType = (Class<?>) returnTypeParameter;
                    } else if (returnTypeParameter instanceof ParameterizedType) {
                        // List<List<UserEntity>> methodRespListNest1();
                        // List<ArrayList<UserEntity>> methodRespListNestArrayList1()
                        // List<ArrayList<?>> methodRespListNestArrayList2()
                        // List<ArrayList<? extends UserEntity>> methodRespListNestArrayList3()
                        // List<ArrayList[]> methodRespListNestArrayList4()
                        System.out.println("returnTypeParameter instanceof ParameterizedType");
                        returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
                        System.out.println(returnType);
                    } else if (returnTypeParameter instanceof GenericArrayType) { // 这个很难命中
                        // List<java.util.ArrayList<UserEntity>[]>  能命中,会报错;java.util.ArrayList<UserEntity> 不是具体类型
                        // List<T[]> methodName() 能命中,会报错; T 不是具体类型
                        // List<byte[]>  methodName()  框架是为了命中这种类型,但是,实际走不到这个case;(byte[]  instanceof Class<?> ) 会为true
                        System.out.println("((GenericArrayType) returnTypeParameter).getGenericComponentType() = " + ((GenericArrayType) returnTypeParameter).getGenericComponentType().getTypeName());
                        System.out.println("returnTypeParameter instanceof GenericArrayType");
                        Class<?> componentType = (Class<?>) ((GenericArrayType) returnTypeParameter).getGenericComponentType(); // 去掉最右边的 []
                        returnType = Array.newInstance(componentType, 0).getClass();
                    }
                }
            } else if (Map.class.isAssignableFrom(rawType)) { // map类型
                System.out.println("Map.class.isAssignableFrom(rawType)");
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                if (actualTypeArguments != null && actualTypeArguments.length == 2) {
                    Type returnTypeParameter = actualTypeArguments[1]; // value 类型
                    if (returnTypeParameter instanceof Class<?>) {
                        // Map<Long,UserEntity> methodRespMap()
                        System.out.println("returnTypeParameter instanceof Class<?>");
                        returnType = (Class<?>) returnTypeParameter;
                        System.out.println(returnType);
                    } else if (returnTypeParameter instanceof ParameterizedType) {
                        // Map<Long,Map<Long,UserEntity>> methodRespMapNest()
                        System.out.println("returnTypeParameter instanceof ParameterizedType");
                        returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
                        System.out.println(returnType);
                    }
                }
            }
        }
        System.out.println("returnType = " + returnType);
        System.out.println();
    }

    /**
     * 获取指定方法
     */
    private static Method getReturnTypeMethod(Class clazz, String methodName) {
        // Method[] methods = clazz.getMethods(); // 获取所有public
        Method[] methods = clazz.getDeclaredMethods(); // 获取所有声明的方法,包括private
        for (Method method : methods) {
            if (methodName.equals(method.getName())) {
                if ((method.getParameterCount() == 1) && method.getParameterTypes()[0] == Method.class) {
                    return method;
                }
            }
        }
        return null;
    }

    /**
     * 获取指定方法
     */
    private static Method getReturnTypeMethodCannotPrivate(Class clazz, String methodName) throws Exception {
        BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
        MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
        for (MethodDescriptor methodDescriptor : methodDescriptors) {
            Method method = methodDescriptor.getMethod();
            System.out.println(method.getName());
            if (methodName.equals(method.getName())) {
                if ((method.getParameterCount() == 1) && method.getParameterTypes()[0] == Method.class) {
                    return method;
                }
            }
        }
        return null;
    }

    private static void parseParams(Method method) {
        System.out.println(method.getParameterTypes()[0]); // interface java.util.List

        Type genericType = method.getGenericParameterTypes()[0];
        if (!(genericType instanceof ParameterizedType)) { // 泛型类型是:可以参数化的类型,如 List<?>
            return;
        }

        ParameterizedType parameterizedType = (ParameterizedType) genericType;
        System.out.println(parameterizedType); // java.util.List<cn.java.demo.ibatis.internal.reflection.UserEntity>

        Class<?> clazz = (Class<?>) parameterizedType.getActualTypeArguments()[0]; // 具体类型
        System.out.println(clazz); // class cn.java.demo.ibatis.internal.reflection.UserEntity
    }

}

 

 

执行结果

------方法定义 void methodRespVoid() ------
void
resolvedReturnType instanceof Class
void.class.equals(returnType)
returnType = void

------方法定义 UserEntity methodRespEntity() ------
class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity
resolvedReturnType instanceof Class
returnType = class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity

------方法定义 UserEntity[] selectListRespArray() ------
class [Lcn.java.demo.ibatis.internal.resolve_return_type.UserEntity;
resolvedReturnType instanceof Class
returnType.isArray(),returnType = class [Lcn.java.demo.ibatis.internal.resolve_return_type.UserEntity;
returnType.getComponentType() = class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity
returnType = class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity

------方法定义 List<UserEntity> methodRespList() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = cn.java.demo.ibatis.internal.resolve_return_type.UserEntity
returnTypeParameter instanceof Class<?>
returnType = class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity

------方法定义 List<List<UserEntity>> methodRespListNest1() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity]]]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity]]
returnTypeParameter instanceof ParameterizedType
interface java.util.List
returnType = interface java.util.List

------方法定义 List<List> methodRespListNest2() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[interface java.util.List]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = java.util.List
returnTypeParameter instanceof Class<?>
returnType = interface java.util.List

------方法定义 List<UserEntity[]> methodRespListNestArray() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class [Lcn.java.demo.ibatis.internal.resolve_return_type.UserEntity;]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = cn.java.demo.ibatis.internal.resolve_return_type.UserEntity[]
returnTypeParameter instanceof Class<?>
returnType = class [Lcn.java.demo.ibatis.internal.resolve_return_type.UserEntity;

------方法定义 List<ArrayList> methodRespListNestArrayList0() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class java.util.ArrayList]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = java.util.ArrayList
returnTypeParameter instanceof Class<?>
returnType = class java.util.ArrayList

------方法定义 List<ArrayList<UserEntity>> methodRespListNestArrayList1() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[ParameterizedTypeImpl [rawType=class java.util.ArrayList, ownerType=null, actualTypeArguments=[class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity]]]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = ParameterizedTypeImpl [rawType=class java.util.ArrayList, ownerType=null, actualTypeArguments=[class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity]]
returnTypeParameter instanceof ParameterizedType
class java.util.ArrayList
returnType = class java.util.ArrayList

------方法定义 List<ArrayList<?>> methodRespListNestArrayList2() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[ParameterizedTypeImpl [rawType=class java.util.ArrayList, ownerType=null, actualTypeArguments=[org.apache.ibatis.reflection.TypeParameterResolver$WildcardTypeImpl@7a81197d]]]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = ParameterizedTypeImpl [rawType=class java.util.ArrayList, ownerType=null, actualTypeArguments=[org.apache.ibatis.reflection.TypeParameterResolver$WildcardTypeImpl@5ca881b5]]
returnTypeParameter instanceof ParameterizedType
class java.util.ArrayList
returnType = class java.util.ArrayList

------方法定义 List<ArrayList<? extends UserEntity>> methodRespListNestArrayList3() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[ParameterizedTypeImpl [rawType=class java.util.ArrayList, ownerType=null, actualTypeArguments=[org.apache.ibatis.reflection.TypeParameterResolver$WildcardTypeImpl@24d46ca6]]]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = ParameterizedTypeImpl [rawType=class java.util.ArrayList, ownerType=null, actualTypeArguments=[org.apache.ibatis.reflection.TypeParameterResolver$WildcardTypeImpl@4517d9a3]]
returnTypeParameter instanceof ParameterizedType
class java.util.ArrayList
returnType = class java.util.ArrayList

------方法定义 List<byte[]> methodRespListNestArrayList4() ------
ParameterizedTypeImpl [rawType=interface java.util.List, ownerType=null, actualTypeArguments=[class [B]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.List
Collection.class.isAssignableFrom(rawType)
returnTypeParameter.getTypeName() = byte[]
returnTypeParameter instanceof Class<?>
returnType = class [B

------方法定义 Map<Long,UserEntity> methodRespMap() ------
ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null, actualTypeArguments=[class java.lang.Long, class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.Map
Map.class.isAssignableFrom(rawType)
returnTypeParameter instanceof Class<?>
class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity
returnType = class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity

------方法定义 Map<Long,Map<Long,UserEntity>> methodRespMapNest() ------
ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null, actualTypeArguments=[class java.lang.Long, ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null, actualTypeArguments=[class java.lang.Long, class cn.java.demo.ibatis.internal.resolve_return_type.UserEntity]]]]
resolvedReturnType instanceof ParameterizedType
rawType = interface java.util.Map
Map.class.isAssignableFrom(rawType)
returnTypeParameter instanceof ParameterizedType
interface java.util.Map
returnType = interface java.util.Map

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值