gpt4 book ai didi

启用 Jacoco 时,具有默认方法的 Java 8 接口(interface)不起作用

转载 作者:IT老高 更新时间:2023-10-28 13:42:47 24 4
gpt4 key购买 nike

我们有一个带有 默认方法 的接口(interface),我们在 JavaKotlin 类中都实现了该接口(interface),我们为非默认方法。

当我们在 Debug模式下运行(没有 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 本身,它就可以工作。我们无法找出确切的问题。

最佳答案

如果您要调用在 interface 中没有 default 实现的方法的 default 实现,则可能会出现此问题你的类明确地实现它。 (但在该 interface< 的 base (parent, super) interface 中有 default 实现)。

示例:假设这些定义:

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!)


这类似于一个错误! 我们使用了 super 关键字。为什么期望 static 方法?!! 还有一点,上面的代码没有任何问题,你可以在任何 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.


我找到的解决方法:

  1. 如果您有权访问 DerivedInterface 的定义,只需重写 methodFromBaseInterface 并将其显式委托(delegate)给它的 super 接口(interface):

    interface DerivedInterface extends BaseInterface {
    @Override default void methodFromBaseInterface() {
    BaseInterface.super.methodFromBaseInterface();
    }
    // ...
    }
  2. 定义一个实现BaseInterface的中间class并从中派生出A。然后运行methodFromBaseInterface间接抛出中间class:

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

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

    注意:如果您的 A 类之前有一个名为 Bsuper,请取消注释 /*extends B*/ .

关于启用 Jacoco 时,具有默认方法的 Java 8 接口(interface)不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50714637/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com