带有默认方法的Java 8接口启用Jacoco时无效的方法

前端之家收集整理的这篇文章主要介绍了带有默认方法的Java 8接口启用Jacoco时无效的方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们有一个使用默认方法的接口,我们在 Java和Kotlin类中实现了该接口,并且我们提供了非默认方法的实现.

当我们在调试模式(没有testCoverageEnabled = true)运行时,应用程序按预期工作.但是当我们使用testCoverageEnabled = true运行不同的配置时,应用程序崩溃并出现以下错误

java.lang.NoSuchMethodError: No static method $$triggerInterfaceInit()V in class Lcom/ui/viewholders/CAViewContract$$CC; or its super classes (declaration of 'ui.viewholders.CAViewContract$$CC' appears in /data/app/SMCXbiLYvHb1Kk08Kee__g==/base.apk)
    at home.c.CCFragment.<clinit>(Unknown Source:0)
    at home.HomePageCardProvider.getFragment(HomePageCardProvider.java:17)
    at home.HomeFragment.handleCardFragment(HomeFragment.java:172)

注意:
1. JaCoCo版本:“0.8.0”
2.操作系统:Android with minSdk 21

如果我们将minSdk更改为24,并且testCoverageEnabled = true本身,则它正在工作.我们无法弄清楚确切的问题.

解决方法

如果要调用在类明确实现它的接口中没有默认实现的方法的默认实现,则会发生此问题. (但是在该接口的基础(父,超)接口中有默认实现).

示例:假设这些定义:

class A implements DerivedInterface /*,...*/ {
    @Override public void methodFromBaseInterface() {
        DerivedInterface.super.methodFromBaseInterface(); // Error:
            // NoSuchMethodError: No static method methodFromBaseInterface
    }
    // ...
}

interface DerivedInterface extends BaseInterface {
    // ... 
    // `methodFromBaseInterface` hasn't overriden here.
}

interface BaseInterface {
    default void methodFromBaseInterface() { /* ...*/ }
    // ...
}

后执行

A a = new A();
a.methodFromBaseInterface(); // This cause above error!

而你在上述点上得到错误

(边注:您可能需要在DerivedInterface中定义至少一个方法,以避免在运行时获取NoClassDefFoundError!)

这类似于一个错误!我们使用超级关键字.为什么要预期静态方法?!!另一点是上面的代码没有任何问题,您可以在任何Java 8兼容环境中运行它没有任何问题!

我认为这个问题与Android平台中Java 8语言API的不完全支持有关:

Android Studio 3.0 and later supports all Java 7 language features and a subset of Java 8 language features that vary by platform version.

that page中特别注意Java 8 Language API和兼容的minSdkVersion表:

java.lang.FunctionalInterface : API level 24 or higher.

我找到的解决方法

>如果您有权访问DerivedInterface的定义,只需覆盖methodFromBaseInterface并将其显式委托给其超级接口:

interface DerivedInterface extends BaseInterface {
    @Override default void methodFromBaseInterface() {
        BaseInterface.super.methodFromBaseInterface();
    }
    // ...
}

>定义一个实现BaseInterface并从中派生A的中间类.然后运行methodFromBaseInterface间接抛出中间类:

class MiddleClass /*extends B*/ implements BaseInterface {}

class A extends MiddleClass implements DerivedInterface {
    @Override public void methodFromBaseInterface() {
        super.methodFromBaseInterface(); // Indirectly from `MiddleClass`
    }
    // ...
}

注意:如果您的A类之前有一个名为B的超级,则取消注释/ *扩展B * /.

猜你在找的Java相关文章