如何使Kotlin停止转换错误的类(接口)

我一直在和最近的Kotlin一起玩,真是太棒了!

我正在使用Twitter4j库来试用Twitter API的一些东西。 我在Kotlin写了这个代码

object Demo { private val twitterStream = TwitterStreamFactory().instance @JvmStatic fun main(args: Array) { val listener = object : StatusListener { override fun onStallWarning(warning: StallWarning?) { println("Got stall warning:" + warning) } override fun onScrubGeo(userId: Long, upToStatusId: Long) { println("Got scrub_geo event userId:$userId upToStatusId:$upToStatusId") } override fun onStatus(status: Status) { println("@" + status.user.screenName + " - " + status.text) } override fun onDeletionNotice(statusDeletionNotice: StatusDeletionNotice) { println("Got a status deletion notice id:" + statusDeletionNotice.statusId) } override fun onTrackLimitationNotice(numberOfLimitedStatuses: Int) { println("Got track limitation notice:" + numberOfLimitedStatuses) } override fun onException(ex: Exception) { ex.printStackTrace() } } twitterStream.addListener(listener) twitterStream.sample() } } 

但每次运行它,我exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class co.enoobong.eno.twitter.bot.Demo at co.enoobong.eno.twitter.bot.Demo.main(Demo.kt:63)

经过进一步调查,Tools-> Kotlin->显示Kotlin字节码。 我反编译为Java,只是发现这是正在生成的东西。

  @JvmStatic public static final void main(@NotNull String[] args) { Intrinsics.checkParameterIsNotNull(args, "args");  listener = new StatusListener() { public void onStallWarning(@Nullable StallWarning warning) { String var2 = "Got stall warning:" + warning; System.out.println(var2); } public void onScrubGeo(long userId, long upToStatusId) { String var5 = "Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId; System.out.println(var5); } public void onStatus(@NotNull Status status) { Intrinsics.checkParameterIsNotNull(status, "status"); String var2 = "@" + status.getUser().getScreenName() + " - " + status.getText(); System.out.println(var2); } public void onDeletionNotice(@NotNull StatusDeletionNotice statusDeletionNotice) { Intrinsics.checkParameterIsNotNull(statusDeletionNotice, "statusDeletionNotice"); String var2 = "Got a status deletion notice id:" + statusDeletionNotice.getStatusId(); System.out.println(var2); } public void onTrackLimitationNotice(int numberOfLimitedStatuses) { String var2 = "Got track limitation notice:" + numberOfLimitedStatuses; System.out.println(var2); } public void onException(@NotNull Exception ex) { Intrinsics.checkParameterIsNotNull(ex, "ex"); ex.printStackTrace(); } }; twitterStream.addListener((StreamListener)listener); twitterStream.sample(); 

}

Kotlin试图将监听器StreamListener为私有的StreamListener (StatusListener扩展它),因此IllegalAccessError

任何想法如何解决请?

PS:下面是一个可用的Java代码版本 – https://github.com/yusuke/twitter4j/blob/master/twitter4j-examples/src/main/java/twitter4j/examples/stream/PrintSampleStream.java

PPS:我在IntelliJ IDEA 2017.2.2上使用Kotlin 1.1.4

Kotlin增加了这些转换以确保在处理重载的方法时调用正确的方法。 发生该问题的原因是公共api addListener需要包 – 私有接口StreamListener 。 试图创建这样一个API实际上是因为这个问题而引发一个警告,并且应该在Twitter4j上进行修复。

在Kotlin中没有直接的方法来解决这个问题,你可以使用一个Java助手类或者一个扩展方法解决这个问题:

 class Twitter4jFixer { public static void addListener(TwitterStream stream, StatusListener listener) { stream.addListener(listener); } } fun TwitterStream.addListenerFixed(listener: StatusListener) { Twitter4jFixer.addListener(this, listener) } 

Kiskae提出了一个很好的观点,也许twitter4j的作者并没有考虑到与其他jvm语言的交互。

我不认为修复是必要的。

如果您必须使用包私有接口twitter4j.StreamListener ,则可以将类放入package twitter4j ,因为不需要的转换。