Kotlin中任何类型和泛型之间的区别

假设我有以下的函数定义。

fun<T> parse(a: Any): T = when (a) { is String -> a else -> false } 

我猜它应该是有效的。 但是,IntelliJ IDEA linter显示类型不匹配错误

Linter错误

这就是说,我会改变我的解析函数的返回类型为Any,对吗? 那么,在Kotlin中使用任何类型和泛型有什么区别呢? 在哪些情况下应该使用每一个?

我读了下面的问题,但根本不了解Kotlin的星空投影,因为我很新。

你的返回类型定义为T ,但是没有什么能保证Ta:Any都有关系。 T可能比Any更受限制,在这种情况下,你不能返回一个布尔值或者你为a提供的任何东西。

以下将通过将返回类型从T更改为Any

 fun<T> parse(a: Any): Any = when (a) { is String -> a else -> false } 

任何其他选项,如果你真的想返回类型T:

 inline fun<reified T> parse(a: Any): T? = when (a) { is T -> a else -> null } 

我猜它应该是有效的

为什么会这样? 你在一个分支中返回一个String在另一个分支中返回一个Boolean 所以when表达式是Any ,这是常见的类型,这就是编译器(和IDEA)所说的“被发现”。 你的代码也说它应该是T (这是“必需的”)。

你的泛型方法应该适用于任何T ,例如Int ,但Any不是Int的子类型,所以代码是无效的。

那么,在Kotlin中使用任何类型和泛型有什么区别呢?

这就像是问“使用数字和文件有什么区别”:它们没有太多共同之处。 你可以使用泛型来编写可以处理所有类型T代码(或者所有类型都满足一定的约束条件)。 当你想要特定的类型Any时,你使用Any

你的例子不使用T ,因此无论如何都是无用的。

想一想:作为一个客户端,你可以把一些东西放到一个函数中,例如一个XML- ByteArray函数应该解析成一个Object 。 调用你不想让它返回的函数Any (Casting sucks),但希望函数返回解析对象的类型。 这可以用泛型来实现:

  fun <T> parse(xml: ByteArray): T { val ctx: JAXBContext = JAXBContext.newInstance() val any = ctx.createUnmarshaller().unmarshal(ByteArrayInputStream(xml)) //return the any here? No, Client wants concrete type T return any as T } val int = parse<Int>("123".toByteArray()) val string = parse<String>("123".toByteArray()) 

看看方法调用:你告诉泛型什么类型是预期返回。 代码是没有用的,只能给你一个泛型的想法。