Java 带子类的条件编译

Java conditional compilation with subclasses

如果有人在其他地方问过这个问题,但我找不到,我深表歉意。

基本上,我想知道带有条件编译的 Java class 是否有效(目的是删除 class 文件中一段代码的所有痕迹)在其子classes.

例如,让我们class A 及其子class B 实现如下:

public class A {
    protected static final boolean ASSERTS = false;

    protected A() {
        if (ASSERTS) {
            System.out.println("A: ASSERTS enabled.");
        }
}

public class B extends A {
    protected B() {
        if (ASSERTS) {
            System.out.println("B: ASSERTS enabled.");
        }
}

很明显什么都不会打印出来。但是,他们的 class 文件会包含编译后的 if 条件吗?

非常感谢!

Java不支持c、c++等宏 您可以使用标志在运行时启用或禁用断言,但不能使用宏

刚刚在 IntelliJ 中编译了 class,然后反编译了 .class 文件以查看它是否包含语句。没有。

我怀疑这取决于编译器(即 Java 语言规范没有说明是否必须包含这些内容,因此可以自由选择),并且您可能会找到一个编译器但是 包含这些语句。我用的是 Corretto Java 11.

不,不会。

您应该尝试创建您的 .class 文件,然后使用反编译器对其进行反编译,或者直接转到 javadecompilers.com 并上传您的 class 文件以确认您的答案。

如果根据您的代码制作源代码

public class A {
protected static final boolean ASSERTS = false;

protected A() {
    if (ASSERTS) {
        System.out.println("A: ASSERTS enabled.");
    }
}

public static class B extends A {
  protected B() {
      if (ASSERTS) {
          System.out.println("B: ASSERTS enabled.");
        }
      }
    }
}

并用 javac 编译,然后用 FALSE 得到字节码

  public class A {
    protected static final boolean ASSERTS;
    protected A();
    Code:
       0: aload_0
       1: invokespecial #2                  // Method java/lang/Object."<init>":()V
       4: return
  }

如果为 TRUE,我们将得到编译后的字节码

public class A {
  protected static final boolean ASSERTS;

  protected A();
    Code:
       0: aload_0
       1: invokespecial #2                  // Method java/lang/Object."<init>":()V
       4: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       7: ldc           #4                  // String A: ASSERTS enabled.
       9: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      12: return
}

以便在 javac 级别上进行此类优化,但为了保证,最好在编译之前删除源代码级别的代码部分,例如使用 preprocessor