当前位置: 首页 > 面试题库 >

Kotlin使用Class调用Java方法 论据

祁烈
2023-03-14
问题内容

我想像这样RestTemplate在Kotlin中使用Spring :

//import org.springframework.web.client.RestTemplate
fun findAllUsers(): List<User> {
        val restTemplate = RestTemplate()

        //has error
        val ret = List<User>.javaClass
        return restTemplate.getForObject(URI(hostAddress), ret)
}

RestTemplate.getForObject(URI url, Class<T> responseType)有这个签名,我从得到这个错误“未解决的参考序列” Listval ret = List<User>.javaClass

如果我这样使用,val ret = List<User>::class.java则会出现此错误“类字面量的左侧仅允许类”

有什么问题?这样做的正确方法是什么?是虫子吗?


问题答案:

@edwin的答案是正确的,您遇到了XY问题,您实际上是在问错了什么。值得庆幸的是,您在执行此操作时遇到了一个错误,这导致您进入此处,@
edwin能够解释执行正确行为的替代方法。

每个Java绑定库都具有类似的模式(Class与类型引用相对)。因此,这是好东西,您可以在您的库中学习和查找,例如RestTemplate,Jackson,GSON等。实用程序类可能ParameterizedTypeReference在一个中,TypeReference在另一个中,TypeRef在另一个中,依此类推;但所有人都在做同一件事。

现在,对于任何想知道原始代码有什么问题的人 ,创建一个泛型擦除的类引用(例如Class<T>语法)将是:

val ref = List::class.java

您会注意到没有办法表达列表中项目的通用类型。即使可以,它们也会由于类型擦除而被擦除。将此传递给绑定库就像说“
请为可能为空的java.lang.Object的列表 ”,但更糟。想象一下Map<String, List<Int>>,您现在在哪里丢失了所有可能反序列化的信息。

以下内容 无法 编译:

val ref = List<String>::class.java  // <--- error only classes are allowed on left side

错误消息可能更清楚地说:“ ::左侧仅允许没有通用参数的类

并且您javaClass只能在实例上使用,因此,如果您碰巧拥有一个方便的列表…

val ref = listOf("one", "two", "three").javaClass

然后,您将得到一个擦除的类型Class<T>,这再次是在这里使用错误的东西,但语法正确。

那么@edwin显示的代码实际上是做什么的呢?

通过创建具有超类型ParameterizedTypeReference的对象,代码可以解决此问题,因为即使删除了类型,任何类都可以通过的镜头看到其超类和接口中的泛型Type。例如:

val xyz = object : MySuperClass<SomeGenerics>() {}

匿名类的该实例具有MySuperClass具有通用参数的超类SomeGenerics。因此,如果MySuperClass包含以下代码:

abstract class MySuperClass<T> protected constructor() {
    val type: Type = (javaClass.genericSuperclass as ParameterizedType)
                                 .actualTypeArguments[0]
}

然后,您可以添加 .type声明的末尾以访问此功能:

val typeOfSomeGenerics = object : MySuperClass<SomeGenerics>() {}.type

现在,您将具有一些Type描述我们的SomeGenerics类的实现。这将是一个:
ClassParameterizedTypeGenericArrayTypeTypeVariable,和WildcardType

通过了解和使用这些知识,一个进行数据绑定的库足以了解其工作。

Kotlin的生活更轻松:

在Kotlin中,编写扩展函数很容易,因此您不必重复执行此类代码。只需创建一个使用内联泛型的助手内联函数来传递类型并创建ParameterizedTypeReference

inline fun <reified T: Any> typeRef(): ParameterizedTypeReference<T> = object: ParameterizedTypeReference<T>(){}

现在,您可以将@edwin的示例更改为:

val response = restTemplate.exchange(request, typeRef<List<String>>())


 类似资料:
  • 我有一个用kotlin编写的库,我想在Java程序中使用它,但我不知道如何正确调用异步方法。 在Java中,我必须向函数传递什么参数?IntelliJ说我需要这样的东西:

  • 增加对SharedReferences调用的可读性。编辑器我想使用一个Kotlin变量来执行“getSharedReferences”。每次我需要一个新的SharedReferences时,编辑()。编辑起初,我打算用这样的东西: 但后来我被告知,“editPreferences”将保留对同一个编辑器的引用,而我真正想要的是在每次调用“editPreferences”时创建一个新的编辑器。 如果使

  • 本文向大家介绍Java调用方法,包括了Java调用方法的使用技巧和注意事项,需要的朋友参考一下 示例 使用反射,可以在运行时调用对象的方法。 该示例显示了如何调用String对象的方法。            

  • 问题内容: 我需要使用反射调用类的setter方法,并且代码如下: 的是一个以及设置器方法如下: 运行此代码时,将引发A ,但是将setter方法参数类型更改为from时,将执行正常。有没有一种方法可以将setter方法的参数保持为超级类型,并且在从类中获取方法时仍无需手动指定参数的类型即可使用反射? 问题答案: 与其他答案相反,有一个非常简单的解决方案。请参阅。它为您提供了一种执行任意反射代码的

  • 我的问题是关于JMeter和BeanShell后处理程序。 我已经用Eclipse开发了一个Java项目,并将该项目导出到一个JAR中。我已经把这个jar放在JMeter的/lib/ext文件夹中。 我不明白为什么当我直接调用jar时它会工作,为什么当我用JMeter做同样的事情时它不会工作。 谢谢你的帮助。

  • 我在将这部分Java转换为Kotlin时遇到了问题: 方法的第二个参数(注意不是集合)接受。我尝试了几个解决方案,包括提供一个lambda: 但这导致: 错误:(32,38)Kotlin:意外标记 错误:(33,38)Kotlin:意外标记 错误:(31,56)Kotlin:类型不匹配:推断的类型是Kfunction1<@parametername mutablehttpresponse<>?,u