kotlin和java混用 空安全的坑

第一种直接引用Java类,隐蔽指数 Mid

再android studio中,使用kotlin 调用一个会返回空的java函数, 是不会提示空安全的,只有加上@nullable之后才会提示。

public static  T jsonToObj(String json, Class tClass) {
    if (TextUtils.isEmpty(json) || tClass == null) {
        return null;
    }
    …
    …
    …
    return item;
}

这样直接调用是不会提示的

val entity = GsonUtil.jsonToObj("", Entity::class.java)
entity.let {}//这里没有空安全提示,但是确实会返回空

所以应该加上@nullable

@nullable
public static  T jsonToObj(String json, Class tClass) {}

这样就会提示空安全了。
所以kotlin调用没有被标记nullable的函数一定要当心!

kotlin和java混用 空安全的坑_第1张图片

第二种 使用一些库,比如Gson,隐蔽指数 Max

我们定义的实体类是可以定义为非空类型的,比如

data class En(val str:String)

这时候在哪里调用这个属性str,编译期都会提示非空,比如
kotlin和java混用 空安全的坑_第2张图片
然鹅,实际真的是这样吗?
我们做一个小小的单元测试就知道了

@Test
fun addition_isCorrect() {
    assertEquals(4, 2 + 2)
    val jsonString = "{str:null}"
    val json = Gson().fromJson(jsonString,En::class.java)
    if (json.str == null) {
        println("test assert json.str = null")
    }
    assertEquals(json.str,null)
}
data class En(val str:String)

kotlin和java混用 空安全的坑_第3张图片
我们数据传入的是jsonString很明显str字段是个空的,gson解析出来也是空的, 所以会打印这句话,而且单元测试的断言是可以tests passed的。可笑的是,IDE还在提示不需要判空。
kotlin和java混用 空安全的坑_第4张图片
可见混用还是不能依赖IDE的提示,需要自己来判断!

虽然说可以再实体类就设置为可空类型, 类似val s:String?,但是未免让kotlin的特意设计(官方介绍大篇幅吹比)的空安全特性显得略显无用武之地,所以这里给出一种解决方案提供给使用Gson而且服务器返回为null并没有特殊含义的同学们使用,就是Gson解析时候使用反射把类型为String且为null的属性赋值为“”。

/**
     * object to json 的工具类
     * 所有为null的String类型都会被赋值为""
     * @param 
     * @return
     */
    public static  T jsonToObj2(String json, Class tClass) {
        if (TextUtils.isEmpty(json) || tClass == null) {
            return null;
        }
        T item = null;
        try {
            Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
                        .enableComplexMapKeySerialization().create();
            item = gson.fromJson(json, tClass);

            Class itemClass = item.getClass();
            Field[] fields = itemClass.getDeclaredFields();
            for (Field f : fields) {
                f.setAccessible(true);
                Type type = f.getGenericType();
                Object obj = f.get(item);
                if (obj == null && type.toString().contains("String")) {
                    f.set(item, "");
                }
            }
        } catch (JsonSyntaxException e2) {
            Log.d(TAG, "jsonToList: JsonSyntaxException error");
        } catch (JsonParseException e1) {
            Log.d(TAG, "jsonToList: JsonParseException error");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return item;
    }

kotlin和java混用 空安全的坑_第5张图片

可以看到通过单元测试,嗯,就酱。

你可能感兴趣的:(android)