调用java.util.spi.ToolProvider在Kotlin中遇重载歧义,如何解决?
解决Kotlin中调用ToolProvider.run的重载歧义问题
你遇到的这个问题我太熟悉了!在Kotlin里调用java.util.spi.ToolProvider的run方法时,编译器会抛出重载歧义错误,原因是这个接口同时存在两个run方法——一个抽象方法接收PrintStream类型的输出流参数,另一个默认方法接收PrintWriter类型的参数。当你传入null作为前两个参数时,Kotlin无法推断你要匹配哪一个方法的参数类型,所以触发了歧义。
几个可行的解决方案:
显式指定null的参数类型
直接给null加上类型转换,明确告诉编译器你要调用哪个版本的run方法。比如如果你想调用接收PrintStream的抽象方法(大部分ToolProvider实现都会优先实现这个版本):val jar = ToolProvider.findFirst("jar").orElseThrow() jar.run(null as PrintStream?, null as PrintStream?, "--create", "file=foo.jar", "--main-class=foo.bar", "-C", "baz", ".")要是你想调用默认的
PrintWriter版本,就换成对应的类型转换:val jar = ToolProvider.findFirst("jar").orElseThrow() jar.run(null as PrintWriter?, null as PrintWriter?, "--create", "file=foo.jar", "--main-class=foo.bar", "-C", "baz", ".")传入具体的流实例(更推荐)
如果你不需要传null,直接传入标准输出/错误流的对应实例,编译器就能自动匹配到正确的方法:
调用PrintStream版本:val jar = ToolProvider.findFirst("jar").orElseThrow() jar.run(System.out, System.err, "--create", "file=foo.jar", "--main-class=foo.bar", "-C", "baz", ".")调用
PrintWriter版本:val jar = ToolProvider.findFirst("jar").orElseThrow() jar.run(PrintWriter(System.out), PrintWriter(System.err), "--create", "file=foo.jar", "--main-class=foo.bar", "-C", "baz", ".")用函数引用明确方法签名
你也可以通过定义函数类型变量来绑定具体的方法版本,消除歧义:val jar = ToolProvider.findFirst("jar").orElseThrow() // 指定绑定接收PrintStream的run方法 val targetRun: (PrintStream?, PrintStream?, Array<String>) -> Int = jar::run targetRun(null, null, arrayOf("--create", "file=foo.jar", "--main-class=foo.bar", "-C", "baz", "."))
补充说明:
Java 9引入ToolProvider时先定义了抽象的PrintStream版本run方法,后续为了适配PrintWriter场景又添加了默认方法。Java编译器能通过上下文自动处理这种重载,但Kotlin的类型推断在面对null这种无类型参数时,没办法自动识别目标方法,所以需要我们显式给出类型提示。
内容的提问来源于stack exchange,提问作者MaxPower
相关产品推荐
相关产品推荐

