#在Java中定义


74

我开始用Java编程,并且想知道是否#define存在与C ++等效的语言。

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

而不是myArray[0]我想能够写myArray[PROTEINS]例如。


9
在现代C ++中,您应该使用类型常量而不是#define
Pete Kirkham 2009年

2
是的,#define是C风格的。在C ++中,请改用const。请参阅Scott Meyers的“有效C ++”书第1项
。– Jabba

Answers:


100

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

class MyClass
{
    private static final int PROTEINS = 0;

    ...

    MyArray[] foo = new MyArray[PROTEINS];

}

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

请注意,在不断的访问修饰符是不重要的在这里,所以它可能是publicprotected不是的私人,如果你想重复使用多个类相同的常数。


43

注释空间太小,因此这里有一些有关的更多信息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);
    }
}

编译并运行Test,打印:

Int    = 0
Value  = A

现在,更改Constants每个类的值,然后编译类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/类似,在常规Java条件中使用#endif常量常量或static final使用原语定义的常量常量,if并求值false会导致编译器剥离if块中语句的字节码(不会生成)。

private static final boolean DEBUG = false;

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

“ ...此处的代码...”中的代码不会被编译为字节码。但是,如果您更改DEBUGtrue,那就可以了。


2
绝对是为工作付出的+1!
Andreas Dolk,2009年

只是想补充一下Java对enums的作用不同。
Seyed Jalal Hosseini

5
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”!


4

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

对于常量,建议将其声明为static finals,例如

private static final int PROTEINS = 100;

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

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


好吧,私有 static finals并不是真正的公共接口的一部分。:)public static finals但是,这是事实。
孟买

@Mombe,正确。我最初是将其写为公开的,但后来却没有更新答案就进行了更改。
notnoop


1

易读的解决方案是使用静态导入。然后,你将不会需要使用AnotherClass.constant

用常量aspublic 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;

    }
}

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


0

最简单的答案是“因为没有预编译器,所以没有直接获得它的方法”, 但是您可以自己完成。使用类,然后将变量定义为final,这样就可以在整个程序中将其假定为常量
不要忘了将final和变量用作public或protected not private,否则您将无法从该类外部访问它



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.