带有默认方法的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) 注意: 如果我们将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的不完全支持有关:
在that page中特别注意Java 8 Language API和兼容的minSdkVersion表:
我找到的解决方法: >如果您有权访问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 * /. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |