Kotlin学习笔记——填坑

关于可变参数和反射的坑——vararg传递的问题

1、java代码写的的测试用例能通过

public class ExampleUnitTest1 {
    @Test
    public void test() {
        a(1, 2);
    }

    public void a(Object... args) {
        b(args);
    }

    public void b(Object... args) {
        Class clazz1 = ExampleUnitTest1.class;
        try {
            Method method = clazz1.getMethod("add", Integer.class, Integer.class);
            method.invoke(this, args);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public void add(Integer a, Integer b) {
        System.out.println(a + b);
    }
}

2、转换成kotlin代码后不能通过

class ExampleUnitTest {
    @Test
    fun test() {
        a(1, 2)
    }

    fun a(vararg args: Any) {
        b(args)
    }

    fun b(vararg args: Any) {
        val clazz1 = ExampleUnitTest::class.java
        val method = clazz1.getMethod("add", Int::class.java, Int::class.java)
        method.invoke(this, args[0])
    }

    fun add(a: Int, b: Int) {
        println(a + b)
    }
}

3、解决方法,在kotlin中使用*操作符,把数组转换成vararg类型。

class ExampleUnitTest {
    @Test
    fun test() {
        a(1, 2)
    }

    fun a(vararg args: Any) {
        b(*args)
    }

    fun b(vararg args: Any) {
        val clazz1 = ExampleUnitTest::class.java
        val method = clazz1.getMethod("add", Int::class.java, Int::class.java)
        method.invoke(this, *args)
    }

    fun add(a: Int, b: Int) {
        println(a + b)
    }
}

关于Kotlin中使用Retrofit的坑——Any变?通配符的问题

1、java代码中不会出现问题

我定义的接口方法如下:

@GET("/index.html")
Observable getQueryMap(@QueryMap Map params);

Retrofit在执行此方法时,会检查GenericParameterTypes,代码如下:

public ServiceMethod build() {

    ……

    for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
            throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType);
        }

    ……

    }
}

这里的parameterTypes 的值为 [java.util.Map]

然后Utils.hasUnresolvableType(parameterType)对应的代码为:

final class Utils {

    ……

    static boolean hasUnresolvableType(Type type) {

        ……

        if (type instanceof WildcardType) {
            return true;
        }

        ……

    }

    ……

parameterTypes 在这里检查没有问题。但是如果type为WildcardType(通配符)就会返回true,从而抛出错误:throw parameterError(p, “Parameter type must not include a type variable or wildcard: %s”, parameterType);
2、Kotlin代码中会出现问题

我定义的接口方法如下:

@GET("/index.html")
fun getQueryMap(@QueryMap paramsMap: Map): Observable

Retrofit在执行此方法时,会检查GenericParameterTypes,这里Any就和java中的Object 不一样了,这里的parameterTypes 的值为 [java.util.Map],从而导致Utils.hasUnresolvableType(parameterType)方法返回true,然后抛出错误:throw parameterError(p, “Parameter type must not include a type variable or wildcard: %s”, parameterType);
3、解决办法
使用non-wildcard 类型 (e. g. MutableMap, MutableList) 或者使用 @JvmSuppressWildcards 注解。

你可能感兴趣的:(Android)