How to make Kotlin stop using the argument for the wrong class (Interface)

I recently talked with Kotlin, and it was awesome!

I worked with the Twitter4j library to try some things using the Twitter API. I wrote this code in Kotlin

object Demo { private val twitterStream = TwitterStreamFactory().instance @JvmStatic fun main(args: Array<String>) { 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() } } 

but every time I ran it I got an 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)

After further study, Tools-> Kotlin-> Show Kotlin Bytecode. I decompiled in Java, but found that this is what was created.

  @JvmStatic public static final void main(@NotNull String[] args) { Intrinsics.checkParameterIsNotNull(args, "args"); <undefinedtype> 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 tried to pass a listener to a StreamListener , which is private in the Library (StatusListener extends it), therefore, IllegalAccessError

Any ideas how to solve please?

PS: Here's the working version of the Java code - https://github.com/yusuke/twitter4j/blob/master/twitter4j-examples/src/main/java/twitter4j/examples/stream/PrintSampleStream.java

PPS: I am using Kotlin 1.1.4, on IntelliJ IDEA 2017.2.2

+5
source share
2 answers

Kotlin adds these casts to ensure that the correct method is called when working with overloaded methods. The problem arises because the public api addListener expecting a addListener private packet interface. An attempt to create such an api actually causes a warning precisely because of this problem and should be fixed on the side of Twitter4j.

There is no direct way to fix this in Kotlin, you can work around the problem using the Java helper class and possibly an extension method:

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

Kiskae set the point. Perhaps the author of twitter4j does not take into account interactions with other jvm languages.

I do not think a correction is necessary.

You can simply put your class in package twitter4j if you have to use the closed twitter4j.StreamListener package twitter4j.StreamListener due to unwanted casting.

0
source

Source: https://habr.com/ru/post/1271031/


All Articles