Jacoco 在运行单元测试时在我的界面中添加了一个 $jacocoInit 方法



在接口中添加 defaut 方法时,我得到了一个不必要的方法$jacocoInit。我的界面看起来像这样:

@Value.Immutable
public interface Customer {

Optional<@NotBlank String> name();
default Object getObject(final String abc) {
return null
}
default void getObject() {
}
}

当我在做

for (Method method : Customer.class.getDeclaredMethods()) {
System.out.println(method.getName());
}

然后,我得到了

name
getObject
$jacocoInit

如果我从中删除默认方法,那么它不会$jacocInit方法。我不确定为什么会这样?有人可以帮忙吗?

根据JaCoCo常见问题解答:

为了收集执行数据,JaCoCo 检测被测试的类,该类向类添加两个成员:私有静态字段$jacocoData和私有静态方法$jacocoInit()。两个成员都标记为合成。

请更改代码以忽略合成成员。无论如何,这是一个很好的做法,因为Java编译器在某些情况下也会创建合成成员。

java.lang.reflect.Method的方法isSynthetic

如果此可执行文件是合成构造,则返回 true;否则返回 false。

所以忽略合成成员:

for (Method method : Customer.class.getDeclaredMethods()) {
if (method.isSynthetic()) {
continue;
}
System.out.println(method.getName());
}

以下是Java编译器创建合成方法的众多示例之一:

import java.lang.reflect.*;
class Example {
interface I {
Runnable r = () -> {}; // lambda
void m();
}
public static void main(String[] args) {
for (Method method : I.class.getDeclaredMethods()) {
System.out.println("name: " + method.getName());
System.out.println("isSynthetic: " + method.isSynthetic());
System.out.println();
}
}
}

使用 JDK1.8.0_152执行

javac Example.java
java Example

生产

name: m
isSynthetic: false
name: lambda$static$0
isSynthetic: true

以下是 Java 虚拟机规范对合成成员的声明:

出现在源代码中的类成员必须使用 Synthetic 属性进行标记,[...]

您可以在其文档和JaCoCo团队完成的演示文稿中阅读有关JaCoCo实现的更多信息,其中还包括其他一些合成结构的示例。

相关内容

最新更新