web-dev-qa-db-ja.com

#define in Java

私はJavaでプログラミングを始めていますが、C++ #defineに相当するものが存在するかどうか疑問に思っています。

グーグルの簡単な検索ではそうではありませんが、Javaに同様のものが存在するかどうかを教えてもらえますか? コードを読みやすくしようとしています。

myArray[0]の代わりに、たとえばmyArray[PROTEINS]を書きたいです。

66
Meir

いいえ、プリコンパイラがないためです。ただし、あなたの場合、次のように同じことを達成できます。

class MyClass
{
    private static final int PROTEINS = 0;

    ...

    MyArray[] foo = new MyArray[PROTEINS];

}

コンパイラは、PROTEINSが変更されることは決してないため、インライン化することに気付くでしょう。

定数のアクセス修飾子はここでは重要ではないため、複数のクラスで同じ定数を再利用する場合は、privateではなくpublicまたはprotectedにすることができます。

91
Andrzej Doyle

コメントスペースが小さすぎるため、static finalの使用に関する詳細情報を次に示します。 Andrzejの答え へのコメントで述べたように、プリミティブとStringのみがリテラルとしてコードに直接コンパイルされます。これを実証するには、次を試してください。

これを実際に見るには、3つのクラスを別々のファイルに作成します。

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を変更してそれぞれに異なる値を設定し、クラス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で定義され、通常のJava if条件で使用され、 falseと評価されると、コンパイラはifブロック内のステートメントのバイトコードを削除します(生成されません)。

private static final boolean DEBUG = false;

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

「... code here ...」のコードは、バイトコードにコンパイルされません。ただし、DEBUGtrueに変更した場合は、変更されます。

38
Kevin Brock
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。また、最後のコンパイルサイクルでコンパイラが「4」を記述した可能性があるため、Barもコンパイルします。

5
extraneon

Javaには、汎用のdefineプリプロセッサディレクティブがありません。

定数の場合、次のようにstatic finalsとして宣言することをお勧めします

private static final int PROTEINS = 100;

このような宣言は、コンパイラーによってインライン化されます(値がコンパイル時定数の場合)。

また、public static final constantフィールドはpublicインターフェースの一部であり、それらの値は変更しないでください(コンパイラーがインライン化するため)。値を変更した場合、その定数フィールドを参照したすべてのソースを再コンパイルする必要があります。

4
notnoop

Javaのプリプロセッサ があり、#define、#ifdef、#ifndefなどのディレクティブを提供します。たとえば、PostgresJDBCチームはこれを使用して、さまざまなケースのソースを生成し、コードを複製しません。

3
Igor Maznitsa

ほとんどの読解可能なソリューションは 静的インポート を使用しています。次に、notAnotherClass.constantを使用する必要があります。

public staticフィールドとして定数を使用してクラスを記述します。

package ConstantPackage;

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

次に、定数が必要な場所でStatic Importを使用します。

import static ConstantPackage.Constant.PROTEINS;

public class StaticImportDemo {

    public static void main(String[]args) {

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

    }
}

静的インポートの詳細については、 このスタックオーバーフローの質問 を参照してください。

最も簡単な答えは 「プリコンパイラがないため、直接取得する方法はありません」 しかし、あなたは自分でそれを行うことができます。クラスを使用し、変数を次のように定義します 最後の そのため、プログラム全体で一定と見なすことができます
finalとvariableをpublicまたはprivateではなくprotectedとして使用することを忘れないでください。そうしないと、そのクラスの外部からアクセスできなくなります。

0
Jitendra Nagar

Java Primitive Specializations Generator は、Javaコードで同様のマクロ生成を行うことができる/* with *//* define */、および/* if */ ... /* Elif */ ... /* endif */ブロックをサポートします。 this answer で言及されているJava-comment-preprocessorに。

JPSGにはMavenおよびGradleプラグインがあります。

0
leventov