Types Kotlin具体化类型参数可以';不能用作函数体中的类型参数

Types Kotlin具体化类型参数可以';不能用作函数体中的类型参数,types,parameters,kotlin,inline,Types,Parameters,Kotlin,Inline,Kotlin中的具体化类型参数可防止类型参数擦除,并允许在运行时知道类型参数。这允许以下代码按预期编译和运行: inline fun <reified T> isA(value: Any) = value is T inline fun isA(值:Any)=值为T 然而,当我尝试使用“T”作为类型参数而不是独立参数时,我得到一条消息,它是一个已擦除的类型。以下代码仅用于说明目的,说明了这一点: inline fun isListOfA(名称:String):布尔值{ val c

Kotlin中的具体化类型参数可防止类型参数擦除,并允许在运行时知道类型参数。这允许以下代码按预期编译和运行:

inline fun <reified T> isA(value: Any) = value is T
inline fun isA(值:Any)=值为T
然而,当我尝试使用“T”作为类型参数而不是独立参数时,我得到一条消息,它是一个已擦除的类型。以下代码仅用于说明目的,说明了这一点:

inline fun isListOfA(名称:String):布尔值{
val candidate=Class.forName(name)
返回候选人名单
}

这是由于技术限制吗?如果是这样,那限制是什么?

在Kotlin中没有办法做到这一点,因为Java在编译时将泛型类型参数
T
擦除为
对象
/上限类型

第一种方法可以工作,因为
值为T
以具体化类型内联到调用站点函数中,例如:

//val is_string = isA<String>(1) // inline into the call-site function as below:


val i:Int = 1
//                   v--- the actual type argument is inlined here
val is_string = 1 is String
//val is_string=isA(1)//内联到调用站点函数中,如下所示:
val i:Int=1
//v---实际的类型参数在这里内联
val为字符串=1为字符串

阻止您这样做的技术限制是。基本上,在运行时,泛型类型
List
的对象只会变成一个与对象一起工作的
List
:只有在编译时,才会检查类型安全性以进行赋值和函数调用。实际类型参数
T
仅在编译时存在,然后被删除。它不能在运行时恢复(至少目前是这样:有一天可能会引入JVM的运行时具体化泛型)

在非内联Kotlin函数中(使用非具体化类型参数),您甚至不能执行第一种检查,
值为T
,因为普通类型参数也会被擦除

使用具体化类型参数,函数体在其调用站点内联,用实际(或推断)类型参数替换
T
:当调用
isA(“abc”)
时,调用站点将具有字节码,字节码带有
instanceof
检查
字符串

但是,即使使用具体化的类型参数,您也无法内省泛型类型:您可以检查
something is List
,但不能检查
something is List
:类型参数在运行时不会存储在任何位置


还要注意,
isA(listOf(1,2,3))
将返回
true
。Kotlin就是这样处理这种奇怪的情况的:只有类型的非泛型部分才能在运行时进行实际检查,事实就是如此。

参数化类型总是在运行时被擦除。因此,您可以检查值是否是
T
实例,而不是
T
实例,无论
T
V
是具体化的还是硬编码的

然而,即使这是可能的,您的示例代码也没有意义,因为它检查具有该名称的类型是否是列表的实例,而不是检查具有该名称的类型是否是预期的列表类型

如果您有一个对象的实例,并且希望检查它是否是一个仅包含预期类型项的列表,您仍然可以编写如下内容:

inline fun <reified T> isListOfA(instance: Any)
    = instance is List<*> && instance.all { it is T }
inline fun isListOfA(实例:Any)
=实例是List&&instance.all{it is T}

显然,我没有恰当地表述我的问题,以得到我想要的形式的答案。这里的大多数答案都是“因为在Java中无法做到这一点”的变体。当然,在Java中也不能执行T的
x实例,但在Kotlin中可以执行
x is T
。我在寻找潜在的实际障碍,而不是Java规则。毕竟,规则是要被打破的

从我对第一个答案的评论来看,重新表述的问题是:如果
objectref是T
可以通过某种机制在Kotlin工作
X
为什么
objectref是SomeClass
不能通过同样的机制工作

tl;dr回答:因为在运行时,
SomeClass
不会有
Class
对象

更详细的回答:首先我们必须理解机制
X
,即为
is T
生成
字节码指令的
实例。此指令获取某类
C
objectref
和名称
N
,其中
N
由编译器根据上下文确定。在运行时,从
N
派生的类
C
将用于计算
objectref is T
表达式。为了进行此计算,必须实例化
C
的类对象。所以对
objectref是SomeClass
使用相同的机制,那么
N
将是
SomeClass
。由于类型擦除,将不会有
SomeClass
的类对象,因此无法生成所需的
指令实例,从而应用相同的机制。此外,
instanceof
指令不能采用
SomeClass
形式的名称。因此,如果
objectref是某个类
要工作,则必须在Kotlin中找到并实现另一种机制
Y
。这种机制可能存在,也可能不存在


我知道有些人可能会说,这与其他一些答案是一样的。然而,不管是好是坏,我的学习风格是理解金属上的东西是如何工作的,然后根据抽象模型综合这些东西。在本例中是Java泛型,擦除的概念是抽象模型(或其一部分)。实际上,“擦除”对我来说是一种软弱无力的感觉,除非我至少了解一种在工作实现中实现它的方式。

是的,我知道实际的类型参数将内联为“is T”as“is”
inline fun <reified T> isListOfA(instance: Any)
    = instance is List<*> && instance.all { it is T }