S-JIS[2008-06-22/2019-12-08] 変更履歴

Javaの定数(リテラル)

固定(不変)の値を表すのが定数


定数値(リテラル)の表現

Javaで定数値(固定の値、即値)を表現するには、以下のようにする。[2003-07-06]

リテラルのデフォルト型
リテラル名 形式
整数リテラル
・「0」で始めると八進数
・「0x」で始めると十六進数
・「0b」で始めると二進数(JDK1.7以降)[2012-01-14]
int 123
0173
0x7b
0b1111011
・末尾にLを付けるとlong型 long 123L
浮動小数リテラル 小数点付きの数 double 123.0
eを使う書き方。mEnはm×10n [2019-12-08] 1.23e10
十六進浮動小数点リテラル。hPnはh×2n(JDK1.5以降)[2019-12-08] 0x1.23p2
・末尾にFを付けるとfloat型
・末尾にDを付けるとdouble型
float
double
123f
123d
文字リテラル シングルクォーテーションで囲む。 char 'A'
文字列リテラル ダブルクォーテーションで囲む。 String "abc"
論理値リテラル true又はfalse boolean true
false
空リテラル null 空型 null

JDK1.7では、数値リテラルの途中でアンダーバーを入れられるようになった。[2012-01-14]

	int n = 123_456;
	int n = 0b111_10111;
×	int n = _123;	//先頭に付けると変数扱いになるのは今まで通り
×	int n = 123_;	//末尾に付けるのも駄目

エスケープ文字(エスケープシーケンス)
文字 コード 機能 備考 関連
\b 08 バックスペース back space  
\f 0C 改ページ form feed  
\n 0A 改行 new line/line feed マシン非依存の改行コードの取得方法
\r 0D 復帰(行頭にカーソルを戻す) carriage return
\t 09 水平タブ horizontal tab  
\\ 5C 「\」    
\' 2C 「'」    
\" 22 「"」    
\ooo   3桁の八進数(000〜377) octal  

Unicodeエスケープ
文字 コード 機能 備考 関連
\uhhhh   4桁の十六進数(0000〜FFFF) hexadecimal \uはコンパイルの第一段階(字句解析)で解釈されるので、
エスケープシーケンスとは動作が異なる

エスケープシーケンスUnicodeエスケープは似て非なるもの。[2008-08-30]
処理の差異


 


不変の変数

finalで宣言して初期値を与えた変数は、定数として扱える。[2008-06-22]
なお、定数として扱う場合は、変数名は全て大文字にするのが慣例。

	public static final int BASE_YEAR = 1970;

この変数には後から値を代入することが出来ない。(finalが付いていると、代入できなくなる)
代入できない→値が不変(固定)→定数

switch文で使う場合の注意
他言語の定数の定義方法


ただし、オブジェクト(参照型)の場合は、必ずしも固定(不変)というわけではない。

	final Map SAMPLE_MAP = new HashMap();

変数SAMPLE_MAPには新しいMapを代入することは出来ない。しかしSAMPLE_MAP内に値をセットするのは自由。

	SAMPLE_MAP.put("key", "value");	//←問題なし

	SAMPLE_MAP = new HashMap(); 	//←これはコンパイルエラーになる

つまり、変数にfinalを付けた場合、あくまでその変数への代入が出来なくなるだけ。
その変数(のクラス)のメソッドやフィールドには普通にアクセスできる。

(すなわち、「finalが付いている」からと言って「不変」というわけではない。この場合は「定数」とは呼び難いので、大文字の変数名にはしない方がいいかも)

StringやInteger等の変更不可能なオブジェクトの場合は、間違いなく定数となる。

	final String STR = "abc";
	final Integer NUMBER = new Integer(1234);

オブジェクトの定数を返すメソッドを作りたい場合は注意が必要。
定数(固定)のつもりで不変でないクラスのオブジェクトを返すと、それが変更されない保証は無い。

class Empty {
	private static final List EMPTY_LIST = new ArrayList(0);

	public List getList() {
		return EMPTY_LIST;
	}
}
		Empty empty = new Empty();
		List list1 = empty.getList();
		list1.add("abc");

		List list2 = empty.getList();
		System.out.println(list2.size());

このgetList()は、用意しておいた空のリストを返している。
しかしその内容は、呼んだ元が書き換えることが出来る。(書き換えることを阻止できない)
したがって、書き換えられてしまった場合、二度目以降の呼び出しでは、空のリストという役を果たしていない…。

C++では(finalに相当する)constキーワードを使って、呼び出した側で値を変更できないように関数(メソッド)定義側で指定できた。

public:
	const List* getList() {
		return EMPTY_LIST;
	}
		const List* list1 = s.getList();
		list1->add("abc");		←「constオブジェクトは変更できない」というコンパイルエラー

Javaで同じように(constに相当する)finalを付けてみると…

	public final List getList() {
		〜
	}

そのメソッドはオーバーライドできないという意味になってしまう(苦笑)

空のコレクション(EMPTY_LISTやEMPTY_MAP) [2008-07-09]
内容も変更できないコレクション(ListやMap)の作り方 [2008-07-09]


switchで使える定数

static finalで定義した変数は定数として使えるので、switch文でも使用できる。[2010-03-06]
のではあるが、値の初期化の仕方によっては使うことが出来ない。

	static final int S1 = 1;
	static final int S2;
	static final int S3 = func();	//メソッド呼び出しによる初期化

	static {	//静的初期化子による初期化
		S2 = 2;
	}

	static int func() {
		return 3;
	}
		int n = 〜;
		switch (n) {
		case S1:
			System.out.println("S1");	break;
		case S2:
			System.out.println("S2");	break;
		case S3:
			System.out.println("S3");	break;
		default:
			System.out.println("def");	break;
		}

case S1は問題ないが、case S2とS3はコンパイルエラーとなる。

S1は変数宣言と同時に初期値を指定しているので、定数として使用できる。
S2,S3は変数宣言時には初期値が無いので、実行時にクラスがロードされて初期化処理が実行されるまで値が定まらない。
switch文の定数はコンパイル時には定まっていないといけない(と思われる)ので、初期値指定の無いstatic final変数はcaseに指定できない。


S2の初期化方法(final宣言をしているが初期値は与えず、静的初期化子によって初期化する)は、finalの特徴を示している。

C言語/C++におけるconstはまさに「定数」を示すものだが、Javaのfinalは「変更できない」ことを意味する。
つまり、どこかで一度だけ初期化できるが、後からその値を変更することが出来ない。
初期化している箇所がどこにも無いとコンパイルエラーになる。
(staticフィールドの場合は静的初期化子、staticでないフィールドの場合はインスタンス初期化子コンストラクター、ローカル変数の場合は使用するまでに初期化する必要がある)
(実行時は、初期化されるまでの間は便宜的にその型のデフォルト値(プリミティブ型の場合は0、参照型の場合はnull)が入っている)


暗黙に定義されている定数

Javaでは以下のような定数が定義されており、使用することが出来る。[2003-07-06]

Javaの定数
リテラル名 定数名 説明
論理値リテラル true booleanの値。「真」を表す。
false booleanの値。「偽」を表す。
空リテラル null オブジェクトのインスタンスが無い状態を表す。

true, false, nullはリテラル(定数)であって、キーワード(予約語)ではないのだそうだ。[/2007-11-13]
すなわち、true,false,nullはコンパイラーが特殊扱いしているのではなく、暗黙にライブラリーによって(?)final変数(定数)として定義されている、ということ。
その証拠に「null = 0;」や「true = false;」といった代入文をJDK1.4やJDK1.5のjavacでコンパイルしてみると、「final 変数 true に値を代入することはできません。」というコンパイルエラーになる。
int if;」といった予約語を使ったコーディングは別のコンパイルエラーになる)

ちなみにtrue, falseの型は言わずと知れたbooleanだが、nullは空型(null型)と言うんだそうだ。[2008-04-08]


環境依存の値

Javaはマルチプラットフォーム対応を標榜している。[2007-02-08]
そこで、プログラムを実行する/稼動させるマシン(環境)によって変わる値を取得する方法が用意されている(ものもある)。

機種依存の定数
概要 取得方法 Windowsの値 UNIXの値
改行コード [/2012-04-12] System.getProperty("line.separator")
System.lineSeparator() //JDK1.7
"\r\n" "\n"
ディレクトリ・ファイル名のパス区切り File.separator
System.getProperty("file.separator")
"\\" "/"
パスの区切り(PATHやCLASSPATH等) File.pathSeparator
System.getProperty("path.separator")
";" ":"

システムプロパティー(System#getProperty())でしか取得できない値は、定数として宣言しておくと便利かも。

	/**
	 * 改行コード
	 */
	public static final String LINE_SEPARATOR = System.getProperty("line.separator");
	public static final String LINE_SEPARATOR = System.lineSeparator(); //JDK1.7以降

Java目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま