Kotlin 中 twitter4j.StreamListner IllegalAccessError 的原因是什么?
What is the reason for twitter4j.StreamListner IllegalAccessError in Kotlin?
在 Kotlin 中实现 twitter4j.StatusListner
时,我得到以下 IllegalAccessError
和关联的堆栈跟踪:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class rxkotlin.rxextensions.TwitterExampleKt$observe
at rxkotlin.rxextensions.TwitterExampleKt$observe.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)
由以下代码生成:
val twitterStream = TwitterStreamFactory().instance
// See
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 }
如果我不使用 Rx,它会使异常更简单一些:
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)
但是,如果我实现 Java 包装器函数,则不会抛出任何错误并且行为符合预期:
包装器-
public class Twitter4JHelper {
public static void addStatusListner(TwitterStream stream, StatusListener listner) {
stream.addListener(listner);
}
}
修改后的实施 -
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 }
这个修改后的解决方案来自 blog post,我认为它试图解释原因,但 Google 翻译不是我的朋友。是什么导致了 IllegalAccessError
?是否有纯粹基于 Kotlin 的解决方案,或者我将不得不接受这种解决方法?
是的,那行不通。
addListener
方法采用 StreamListener
参数并且 StreamListener
是非 public(包私有)。为此,我肯定会针对 Kotlin 编译器提出错误。
Kotlin 编译器生成的代码是:
TwitterStream twitterStream = (new TwitterStreamFactory()).getInstance();
twitterStream.addListener((StreamListener)(new StatusListener() {
// ..overrides ...
}));
StatusListener
已经实现了 StreamListener
所以我不明白为什么需要强制转换。
我使用 java 实用程序 class 解决了这个问题:
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);
}
}
您可以从 Kotlin 调用这些方法,一切都会按预期进行。
在 Kotlin 中实现 twitter4j.StatusListner
时,我得到以下 IllegalAccessError
和关联的堆栈跟踪:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class twitter4j.StreamListener from class rxkotlin.rxextensions.TwitterExampleKt$observe
at rxkotlin.rxextensions.TwitterExampleKt$observe.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)
由以下代码生成:
val twitterStream = TwitterStreamFactory().instance
// See
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 }
如果我不使用 Rx,它会使异常更简单一些:
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)
但是,如果我实现 Java 包装器函数,则不会抛出任何错误并且行为符合预期:
包装器-
public class Twitter4JHelper {
public static void addStatusListner(TwitterStream stream, StatusListener listner) {
stream.addListener(listner);
}
}
修改后的实施 -
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 }
这个修改后的解决方案来自 blog post,我认为它试图解释原因,但 Google 翻译不是我的朋友。是什么导致了 IllegalAccessError
?是否有纯粹基于 Kotlin 的解决方案,或者我将不得不接受这种解决方法?
是的,那行不通。
addListener
方法采用 StreamListener
参数并且 StreamListener
是非 public(包私有)。为此,我肯定会针对 Kotlin 编译器提出错误。
Kotlin 编译器生成的代码是:
TwitterStream twitterStream = (new TwitterStreamFactory()).getInstance();
twitterStream.addListener((StreamListener)(new StatusListener() {
// ..overrides ...
}));
StatusListener
已经实现了 StreamListener
所以我不明白为什么需要强制转换。
我使用 java 实用程序 class 解决了这个问题:
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);
}
}
您可以从 Kotlin 调用这些方法,一切都会按预期进行。