私はJavaでプログラミングを始めていますが、C++ #define
に相当するものが存在するかどうか疑問に思っています。
グーグルの簡単な検索ではそうではありませんが、Javaに同様のものが存在するかどうかを教えてもらえますか? コードを読みやすくしようとしています。
myArray[0]
の代わりに、たとえばmyArray[PROTEINS]
を書きたいです。
いいえ、プリコンパイラがないためです。ただし、あなたの場合、次のように同じことを達成できます。
class MyClass
{
private static final int PROTEINS = 0;
...
MyArray[] foo = new MyArray[PROTEINS];
}
コンパイラは、PROTEINS
が変更されることは決してないため、インライン化することに気付くでしょう。
定数のアクセス修飾子はここでは重要ではないため、複数のクラスで同じ定数を再利用する場合は、privateではなくpublic
またはprotected
にすることができます。
コメントスペースが小さすぎるため、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 ...」のコードは、バイトコードにコンパイルされません。ただし、DEBUG
をtrue
に変更した場合は、変更されます。
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
もコンパイルします。
Javaには、汎用のdefine
プリプロセッサディレクティブがありません。
定数の場合、次のようにstatic finals
として宣言することをお勧めします
private static final int PROTEINS = 100;
このような宣言は、コンパイラーによってインライン化されます(値がコンパイル時定数の場合)。
また、public static final constantフィールドはpublicインターフェースの一部であり、それらの値は変更しないでください(コンパイラーがインライン化するため)。値を変更した場合、その定数フィールドを参照したすべてのソースを再コンパイルする必要があります。
Javaのプリプロセッサ があり、#define、#ifdef、#ifndefなどのディレクティブを提供します。たとえば、PostgresJDBCチームはこれを使用して、さまざまなケースのソースを生成し、コードを複製しません。
ほとんどの読解可能なソリューションは 静的インポート を使用しています。次に、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として使用することを忘れないでください。そうしないと、そのクラスの外部からアクセスできなくなります。
Java Primitive Specializations Generator は、Javaコードで同様のマクロ生成を行うことができる/* with */
、/* define */
、および/* if */ ... /* Elif */ ... /* endif */
ブロックをサポートします。 this answer で言及されているJava-comment-preprocessorに。
JPSGにはMavenおよびGradleプラグインがあります。