79

我开始用 Java 编程,我想知道是否#define存在与 C++ 等价的东西。

快速搜索谷歌说它没有,但是谁能告诉我Java中是否存在类似的东西?我正在尝试使我的代码更具可读性。

myArray[0]例如,我希望能够写而不是myArray[PROTEINS]

4

9 回答 9

107

不,因为没有预编译器。但是,在您的情况下,您可以实现以下相同的目标:

class MyClass
{
    private static final int PROTEINS = 0;

    ...

    MyArray[] foo = new MyArray[PROTEINS];

}

编译器会注意到它PROTEINS永远不会改变,因此会内联它,这或多或少是你想要的。

请注意,常量上的访问修饰符在这里并不重要,因此如果您想在多个类中重用相同的常量,它可以是私有的,也可以不是私有的publicprotected

于 2009-12-18T09:00:59.700 回答
45

评论空间太小,所以这里有一些关于使用的更多信息static final。正如我在对Andrzej 的回答的评论中所说的那样,只有原始的并且String作为文字直接编译到代码中。为了证明这一点,请尝试以下操作:

您可以通过创建三个类(在单独的文件中)来看到这一点:

public class DisplayValue {
    private String value;

    public DisplayValue(String value) {
        this.value = value;
    }

    public String toString() {
        return value;
    }
}

public class Constants {
    public static final int INT_VALUE = 0;
    public static final DisplayValue VALUE = new DisplayValue("A");
}

public class Test {
    public static void main(String[] args) {
        System.out.println("Int   = " + Constants.INT_VALUE);
        System.out.println("Value = " + Constants.VALUE);
    }
}

编译这些并运行测试,它会打印:

Int    = 0
Value  = A

现在,更改Constants为每个都有不同的值,然后编译 class Constants。当您Test再次执行(不重新编译类文件)时,它仍然会打印旧值INT_VALUE但不是VALUE. 例如:

public class Constants {
    public static final int INT_VALUE = 2;
    public static final DisplayValue VALUE = new DisplayValue("X");
}

在不重新编译的情况下运行测试Test.java

Int    = 0
Value  = X

请注意,使用的任何其他类型static final都保留为参考。

与 C/C++ #if/类似#endif,常量文字或通过static final原语定义的常量文字,在常规 Javaif条件中使用并计算false结果将导致编译器剥离if块内语句的字节码(不会生成它们)。

private static final boolean DEBUG = false;

if (DEBUG) {
    ...code here...
}

“...code here...”处的代码不会被编译成字节码。但是,如果您更改DEBUG为,true那就是。

于 2009-12-18T09:44:18.910 回答
6
static final int PROTEINS = 1
...
myArray[PROTEINS]

您通常会将“常量”放在类本身中。请注意,允许编译器优化对它的引用,因此除非重新编译所有使用类,否则不要更改它。

class Foo {
  public static final int SIZE = 5;

  public static int[] arr = new int[SIZE];
}
class Bar {
  int last = arr[Foo.SIZE - 1]; 
}

编辑周期SIZE=4…… 还要编译Bar,因为您的编译器可能在最后一个编译周期中刚刚写了“4”!

于 2009-12-18T09:00:14.183 回答
4

Java 没有通用的define预处理器指令。

在常量的情况下,建议将它们声明为static finals,如

private static final int PROTEINS = 100;

这样的声明将由编译器内联(如果该值是编译时常量)。

另请注意,公共静态最终常量字段是公共接口的一部分,它们的值不应更改(因为编译器内联它们)。如果您确实更改了该值,则需要重新编译引用该常量字段的所有源。

于 2009-12-18T09:00:19.190 回答
3

Java的预处理器提供 #define、#ifdef、#ifndef 和许多其他指令,例如 PostgresJDBC 团队使用它为不同的情况生成源代码并且不重复代码。

于 2018-01-18T20:55:35.297 回答
1

易读的解决方案是使用Static Import。那么您将不需要使用AnotherClass.constant.

编写一个以常量为public static字段的类。

package ConstantPackage;

public class Constant {
    public static int PROTEINS = 1;
}

然后只需在需要常量的地方使用静态导入。

import static ConstantPackage.Constant.PROTEINS;

public class StaticImportDemo {

    public static void main(String[]args) {

        int[] myArray = new int[5];
        myArray[PROTEINS] = 0;

    }
}

要了解有关静态导入的更多信息,请参阅此堆栈溢出问题

于 2018-01-02T13:38:54.417 回答
1

作为 javac 编译器插件实现的Manifold Preprocessor专为Java 源代码的条件编译而设计。它使用熟悉的 C/C++ 指令风格:#define、#undef、#if、#elif、#else、#endif、#error。和#warning。

它有 Maven 和 Gradle 插件。

于 2020-07-05T20:42:51.817 回答
0

最简单的答案是“没有直接的方法,因为没有预编译器” 但是你可以自己做。使用类,然后将变量定义为final,以便在整个程序中将其假定为常量
不要忘记将 final 和变量用作公共或受保护的非私有,否则您将无法从该类外部访问它

于 2017-05-30T11:25:36.607 回答
0

Java Primitive Specializations Generator支持/* with */,/* define *//* if */ ... /* elif */ ... /* endif */允许在 Java 代码中生成某种宏的块,类似于这个答案中提到的 java-comment-preprocessor 。

JPSG 有 Maven 和 Gradle 插件。

于 2019-04-08T18:44:14.157 回答