¿Cuál es el motivo de twitter4j.StreamListner IllegalAccessError en Kotlin?

Al implementar un twitter4j.StatusListner en Kotlin, obtengo el siguiente IllegalAccessError y el IllegalAccessError asociado de la stack:

 Exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class rxkotlin.rxextensions.TwitterExampleKt$observe$1 at rxkotlin.rxextensions.TwitterExampleKt$observe$1.subscribe(TwitterExample.kt:50) at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40) at io.reactivex.Observable.subscribe(Observable.java:10700) at io.reactivex.Observable.subscribe(Observable.java:10686) at io.reactivex.Observable.subscribe(Observable.java:10615) at rxkotlin.rxextensions.TwitterExampleKt.main(TwitterExample.kt:8) 

Producido por el siguiente código:

 val twitterStream = TwitterStreamFactory().instance // See https://stackoverflow.com/questions/37672023/how-to-create-an-instance-of-anonymous-interface-in-kotlin/37672334 twitterStream.addListener(object : StatusListener { override fun onStatus(status: Status?) { if (emitter.isDisposed) { twitterStream.shutdown() } else { emitter.onNext(status) } } override fun onException(e: Exception?) { if (emitter.isDisposed) { twitterStream.shutdown() } else { emitter.onError(e) } } // Other overrides. }) emitter.setCancellable { twitterStream::shutdown } 

Si no uso Rx, hace la exception un poco más simple:

 twitterStream.addListener(object: twitter4j.StatusListener { override fun onStatus(status: Status) { println("Status: {$status}") } override fun onException(ex: Exception) { println("Error callback: $ex") } // Other overrides. }) Exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class rxkotlin.rxextensions.TwitterExampleKt at rxkotlin.rxextensions.TwitterExampleKt.main(TwitterExample.kt:14) 

Sin embargo, si implemento una function de envoltura de Java, no se produce ningún error y el comportamiento es el esperado:

Wrapper –

 public class Twitter4JHelper { public static void addStatusListner(TwitterStream stream, StatusListener listner) { stream.addListener(listner); } } 

Implementación revisada –

 val twitterStream = TwitterStreamFactory().instance val listner = object: StatusListener { override fun onStatus(status: Status?) { if (emitter.isDisposed) { twitterStream.shutdown() } else { emitter.onNext(status) } } override fun onException(e: Exception?) { if (emitter.isDisposed) { twitterStream.shutdown() } else { emitter.onError(e) } } // Other overrides. } Twitter4JHelper.addStatusListner(twitterStream, listner) emitter.setCancellable { twitterStream::shutdown } 

Esta solución revisada proviene de una publicación de blog , que creo que intenta explicar la causa, pero Google translate no es mi amigo. ¿Qué está causando el IllegalAccessError ? ¿Hay una solución puramente basada en Kotlin, o tendré que vivir con esta solución?

    Sí, eso no va a funcionar.

    addListener método addListener toma un StreamListener y StreamListener no es público (package privado). Definitivamente plantearía un error contra el comstackdor de Kotlin para esto.

    El código que el comstackdor de Kotlin genera es:

     TwitterStream twitterStream = (new TwitterStreamFactory()).getInstance(); twitterStream.addListener((StreamListener)(new StatusListener() { // ..overrides ... })); 

    StatusListener ya implementa StreamListener por lo que no veo por qué se requiere el elenco.

    Trabajé alnetworkingedor de esto usando una class de utilidad java:

     public class T4JCompat { public static void addStatusListener(TwitterStream stream, StatusListener listener) { stream.addListener(listener); } public static void removeStatusListener(TwitterStream stream, StatusListener listener) { stream.removeListener(listener); } } 

    Puede llamar a estos methods desde Kotlin y las cosas funcionan como se espera.