如何让Kotlin停止向错误的类转换参数(接口)

Eno*_*ong 5 java twitter4j kotlin

我最近和Kotlin一直在闲逛,这真是太棒了!

我正在使用Twitter4j库来试用Twitter API的一些东西.我在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()

    }
}
Run Code Online (Sandbox Code Playgroud)

但每次我跑它,我得到了 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-> Show Kotlin Bytecode.我反编译为Java,却发现这就是生成的内容.

 @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();
Run Code Online (Sandbox Code Playgroud)

}

Kotlin试图将侦听器转换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

Kis*_*kae 2

Kotlin 添加这些强制转换是为了确保在处理重载方法时调用正确的方法。出现此问题的原因是公共 apiaddListener需要包私有接口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)
}
Run Code Online (Sandbox Code Playgroud)