我正在尝试将Java代码转换为Kotlin代码:

class TypefaceProvider {
    companion object {
        private var tmpTypeface = Hashtable<String,Typeface>()
        @JvmStatic
        fun getTypeface(context : Context, dir : String, name : String) : Typeface {
            var createTypeface : Typeface? = tmpTypeface[name]
            if(createTypeface == null){
                createTypeface = try{
                    Typeface.createFromAsset(context.assets,"$dir/$name")
                } catch (e : Exception){
                    Log.e(TAG, "fail. msg:${e.message}")
                    Typeface.DEFAULT
                } finally {
                    tmpTypeface[name] = createTypeface
                }
            }
            return createTypeface <--- wrong, type mismatch
        }
    }
}


我想返回一个非null的字体对象,

我已经检查了createTypeface不是null

如何解决返回类型不匹配的问题?

我应该使用return createTypeface!!还是

createTypeface?:Typeface.DEFAULT(但Typeface.DEFAULT是重复的)

还是其他?

最佳答案

简短的答案是-如果您确定createTypeface确实不是null,则可以安全地返回createTypeface!!。您断言某些您知道是真实的事情。看来您正在执行此操作,因此!!在这种情况下应该可以正常工作。

通常,如果您希望Kotlin推断出某些不是null的东西,则需要确保您永远不会将null设置为可能的值。您的示例的一种选择是将空检查折叠为?:运算符-

class TypefaceProvider {
    companion object {
        private var tmpTypeface = Hashtable<String, Typeface>()
        @JvmStatic
        fun getTypeface(context: Context, dir: String, name: String): Typeface {
            val createTypeface = tmpTypeface[name] ?: try {
                Typeface.createFromAsset(context.assets, "$dir/$name")
            } catch (e: Exception) {
                Log.e(TAG, "fail. msg:${e.message}")
                Typeface.DEFAULT
            }
            tmpTypeface[name] = createTypeface`
            return createTypeface
        }
    }
}


请注意,我们必须将tmpTypeface[name] = createTypefacefinally块中拉出。它使您的缓存始终保存null值(请参见下面的@Alexy Romanov的注释)。顺便说一句,我觉得最好不要在finally块中使用它,变量赋值内部的副作用似乎很奇怪。同样,我们不必给出createTypeface和显式类型,因为可以推断出它。

如果您想让内容更具可读性,可以将加载/缓存逻辑分为一个单独的方法-

class TypefaceProvider {
    companion object {
        private var tmpTypeface = Hashtable<String, Typeface>()

        private fun loadTypeFace(context: Context, dir: String, name: String): Typeface {
            val typeface = try {
                Typeface.createFromAsset(context.assets, "$dir/$name")
            } catch (e: Exception) {
                Typeface.DEFAULT
            }
            tmpTypeface[name] = typeface
            return typeface
        }

        @JvmStatic
        fun getTypeface(context: Context, dir: String, name: String) =
            tmpTypeface[name] ?: loadTypeFace(context, dir, name)
    }
}

09-11 17:25