2017-06-14 39 views
2

當實現在科特林一個twitter4j.StatusListner,我得到以下IllegalAccessError和相關的堆棧跟蹤:Kotlin中twitter4j.StreamListner IllegalAccessError的原因是什麼?

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) 

由以下代碼製作:

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 } 

如果我不使用的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,我認爲試圖解釋的原因,但谷歌翻譯是不是被我的朋友。什麼導致IllegalAccessError?有沒有純粹的基於Kotlin的解決方案,還是我必須接受這種解決方法?

+0

如何發佈實際堆棧跟蹤? – Strelok

+0

我已經添加了。 – amb85

回答

1

是的,這是行不通的。

addListener方法需要StreamListener帕拉姆和StreamListener是非公開(包私人)。我肯定會爲此提出針對Kotlin編譯器的錯誤。

代碼科特林編譯器生成的是:

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

StatusListener已經實現StreamListener所以我不明白爲什麼需要投。

+0

聽起來像https://youtrack.jetbrains.com/issue/KT-11700 –

+0

是的,和3張票有關。我想JB並不急於修復它。 – Strelok

+0

我已將我的塔彭斯價值添加到問題跟蹤器。 – amb85

0

我工作圍繞這通過使用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); 
    } 

} 

您還可以從科特林這些方法和工作的事情如預期。