Movatterモバイル変換


[0]ホーム

URL:


S-JIS[2008-05-21/2023-09-23]変更履歴

Javaの型

Javaの型には、基本的な型(プリミティブ型:PrimitiveType)と参照型(ReferenceType)(および、特殊な空型(null type))が存在する。


プリミティブ型(基本的な型)

コンピューター(CPU)が自然に扱えるのがプリミティブ型[2008-05-21]
booleanとかcharはそうとも言えないが、プログラム言語の基礎的な型として用意されているのだろう。

プリミティブ型の整数(整数型:IntegralType)は2の補数表現で値が保持される。[2008-07-03]
浮動小数点数型(FloatingPointType)はIEEE754規格の数値型。[2008-08-30]
数値(リテラル)の書き方(表現方法)

Javaのプリミティブ型には、対応するラッパークラスがある。[2003-07-06]
プリミティブ型はオブジェクトではないので、(オブジェクトしか扱えない)コレクションに格納する時などにはラッパークラスを使用する。
また、プリミティブ型に属する情報(本来プリミティブ型が主管となるべき情報)(最大値・最小値とか特別な定数など)もラッパークラスに定義されている。
(ちなみにこれらのラッパークラスのほとんどは、共通のNumberクラスから派生している)

各プリミティブ型が何ビットなのかは、JDK1.5以降では該当ラッパークラスのSIZEという定数フィールドで表現されている。[2010-03-23]
JDK1.8ではBYTESという定数フィールドも定義され、何バイトなのかも表現されている。[2014-03-19]
(例えばIntger.SIZEは32ビット、Byte.SIZEは8ビット。したがってintのバイト数はInteger.BYTESInteger.SIZE/Byte.SIZE=4)

基本的なデータ型
データ型説明大きさ[bit]値の範囲
(最小値〜最大値)
デフォルト値備考ラッパークラス
void型無し   [2010-03-23]java.lang.Void
boolean真偽値1true ,falsefalse整数値(0や1)の代入はエラーjava.lang.Boolean
charUnicode文字
コードポイント
160〜FFFF0000char c = 'あ';
全角も半角も可
java.lang.Character
byte符号付き整数8-128〜1270 java.lang.Byte
short符号付き整数16-32768〜327670 java.lang.Short
int符号付き整数32-2147483648〜2147483647
普通はInteger.MIN_VALUEInteger.MAX_VALUEを使用
0十進数で9桁まで入る
int i = 999999999;
java.lang.Integer
long符号付き整数64-9223372036854775808〜9223372036854775807
普通はLong.MIN_VALUELong.MAX_VALUEを使用
0十進数で18桁まで入る
long l = 123456L;
java.lang.Long
float浮動小数32単精度(有効桁数が最低でも6桁)
使うならFloat.MIN_VALUEFloat.MAX_VALUE
0.0float f = 123.456F;java.lang.Float
double浮動小数64倍精度(有効桁数が最低でも15桁)
使うならDouble.MIN_VALUEDouble.MAX_VALUE
0.0double d = 123.456;
double d = 123.456d;
double d = 1.23456e2;
java.lang.Double
-任意精度整数 無限?(整数)  java.math.BigInteger
-任意精度符号付十進数 無限?(小数)  java.math.BigDecimal
-原子的更新可能boolean  falseJDK1.5以降AtomicBoolean
-原子的更新可能int  0AtomicInteger
-原子的更新可能long  0AtomicLong

C言語と異なり、unsigned(符号なし)は存在しない。
符号有りか無しかで結果が異なるのは右シフト演算だが、符号有り用と無し用の二種類の演算子が用意されている(演算子によって区別する)。
JDK1.8で符号なし整数を扱うメソッドが追加された

byte→short→int→long、float→double(型の大きさが大きくなる方向)の代入は暗黙に変換される。(プリミティブ型のワイドニング変換:widening primitive conversion)
逆(型の大きさが小さくなる方向)の代入は、明示的に型を指定しないとコンパイルエラーとなる。(プリミティブ型のナローイング変換:narrowing primitive conversion)

int i = 123;double d = i;//キャスト不要
double d = 1.2;int i = (int)d;//明示的なキャストが必要

ただし、定数式に関してはコンパイル時に自動的に変換されてエラーにならないことがある。[2008-04-07]

long l = 123L;short s1 = (int)l; //コンパイルエラーshort s2 = (short)l;//問題なし(通常のキャスト)(long→shortへキャスト)
short s3 = (int)123L;//問題なし(定数式が自動変換された)(long→intへキャスト→shortへ自動変換)

符号なし整数

Javaではプリミティブ型の整数は符号付きである。[2014-03-19]
が、JDK1.8で符号なし整数として扱うメソッドがラッパークラスに追加された。

説明備考
Integer.toUnsignedString(0xffffffff)4294967295符号なし整数として文字列化する。Integer.toString(0xffffffff)-1
Integer.parseUnsignedInt("4294967295")-1符号なし整数として文字列からintを生成する。Integer.parseInt("4294967295")NumberFormatException
Integer.parseUnsignedInt("+1")1Integer.parseInt("+1")1
Integer.parseUnsignedInt("-1")NumberFormatExceptionInteger.parseInt("-1")-1
Integer.compareUnsigned(0xffffffff, 0x7fffffff)1符号なし整数として比較する。Integer.compare(0xffffffff, 0x7fffffff)-1
Short.toUnsignedInt((short)0xffff)65535符号なし整数としてint化する。(short)0xffff-1
Integer.toUnsignedLong(0xffffffff)4294967295符号なし整数としてlong化する。(long)0xffffffff-1
Integer.divideUnsigned(0xffffffff, 2)2147483647符号なし整数として除算する。0xffffffff / 20
Integer.remainderUnsigned(0xffffffff, 4)3符号なし整数として除算した余りを返す。0xffffffff % 4-1

Byte・Short・Integer・Longに同様のメソッドが用意されている。

除算以外(加算・減算・乗算)のメソッドが用意されていないのは、普通の演算子を使っても(その型のビット数に収まっている限りは)符号あり・符号なしで相違が無いからだろう。


参照型

プリミティブ型以外は、全て参照型[/2008-05-21]
「参照型」と呼ばれる理由は、実態はC言語でいうところのポインター(すなわち“参照”)だから。
(つまり参照型の変数が保持する値は、オブジェクトの内容そのものではなく、メモリー上に格納されたオブジェクトの先頭アドレスに当たるものプリミティブ型の変数では、値そのものを保持している)。オブジェクトを使うときは、そのアドレスを元にオブジェクトへアクセスする。これを“参照する”と呼んでいる)

クラス(インスタンス・オブジェクト)文字列(String)配列も、全て参照型。
参照型のデフォルト値はnull。

Stringは、ユーザー定義型(クラス)。コンパイルされると、内部ではUnicodeで扱われる。
Stringも参照型なので、デフォルト値は空文字列などではなく、null。

全ての参照型はObjectクラスから派生している(Objectクラスを継承している)。

参照型の変数へ代入する例
時系列ソーススタックヒープ解説
変数var1変数var2Objectインスタンス領域
1Object var1 = null;null--ローカル変数var1の宣言
2Object var2 = null;nullnull-ローカル変数var2の宣言
3var1 = new Object();0xC000nullObjectインスタンス(生成)
先頭アドレスを0xC000とする
インスタンスを生成しvar1に代入
4var2 = var1;0xC0000xC000Objectインスタンス(0xC000)var1の値をvar2に代入
(参照を渡しているだけなので、同じインスタンスを指す)
5var1 = null;null0xC0000Objectインスタンス(0xC000) 
6var2 = null;nullnullOjbectインスタンス(0xC000) 
7   -0xC000のインスタンスがどこからも参照されなくなったので
GCによりヒープから削除される。

(参考)プリミティブ型の変数へ代入する例
時系列ソーススタックヒープ解説
変数var1変数var2 
1int var1 = 0;0--ローカル変数var1の宣言
2int var2 = 0;00-ローカル変数var2の宣言
3var1 = 123;1230-値をvar1に代入
4var2 = var1;123123-var1の値をvar2に代入
5var1 = 0;0123- 
6var2 = 0;00- 
     プリミティブ型はヒープとは何ら関係ない。
したがってGCとも無関係。

参照型で比較する例
時系列ソーススタックヒープ解説
変数var1変数var21つ目2つ目
1String var1 = new String("abc");0xC000-String生成
アドレスを0xC000とする
-ローカル変数var1の宣言
2String var2 = new String("abc");0xC0000xC100Stringインスタンス(0xC000:"abc")String生成
アドレスを0xC100とする
ローカル変数var2の宣言
3if (var1.equals(var2)) 〜0xC0000xC100Stringインスタンス(0xC000:"abc")Stringインスタンス(0xC100:"abc")var1の参照先(0xC000の中身)とvar2の参照先(0xC100の中身)を比較
→ 一致
4if (var1 == var2) 〜0xC0000xC100Stringインスタンス(0xC000:"abc")Stringインスタンス(0xC100:"abc")var1の値(0xC000)とvar2の値(0xC100)を比較
→ 不一致

スーパークラスの変数への代入は、特に問題なく行える。(参照型のワイドニング変換:wideningreference conversion[2008-08-30]
逆の代入(いわゆるダウンキャスト)は明示的なキャストが必要。(参照型のナローイング変換:narrowing reference conversion)

ナローイング変換が正しく行えることを事前チェックする目的でinstanceofが使われる。

class C1 {}class C2 extends C1 {}
C1 c = new C2();//ワイドニング変換if (c instanceof C2) {C2 d = (C2)c; //ナローイング変換}

変数の初期化(デフォルト値)

Javaでは、ローカル変数を初期化しないで使おうとする(初期化されずに使われる可能性がある)と、コンパイルエラーになる(基本的なデータ型であっても)。[2008-05-21]
C言語ではローカル変数を初期化しないと値が不定となる為、初期化しないのはご法度だった)
ローカル変数無初期化の勧め(?)

しかし、クラスのフィールド(メンバー変数)で初期値を指定していない場合newで作った配列で各要素を明示的に初期化していない場合デフォルト値が入れられる。
デフォルト値は それぞれの型によって定められている。(booleanならfalse、その他のプリミティブ型は0、参照型はnull)


型変換

オブジェクト(参照型)からStringへ変換するには、toString()メソッドがよく使われる。[2008-05-21]
全てのクラスの親であるObjectクラスにはtoString()が定義されており、継承したサブクラスではそれをオーバーライドして文字列(String)への独自の変換処理を行う/行ってよい/行うのがよい。

String等から他クラス(自作クラス)への変換は、ラッパークラス列挙型(enum)に倣ってvalueOf()を実装する…のがいいかなぁ。[/2009-12-31]
クラスによってはparse()とかdecode()というのもあるけど。

プリミティブ型に関する操作は、たいてい対応するラッパークラスに揃っている。[2007-06-30]
ちなみにこれらのラッパークラスのほとんどは 共通のNumberクラスを継承しているので、例えばintへ変換するintValue()はIntegerでもLongでもDoubleでもByteでも使える。

ラッパークラスにはコンストラクターがあるが、Java9から非推奨になった。[2021-03-21]
たいていはvalueOfメソッドでインスタンスを生成する。
Java16で、ラッパークラスのコンストラクターは削除対象(将来削除される)になった。

代表的な型変換
変換(左←右)備考更新日
intStringint i=Integer.parseInt(String)全角文字の数字も変換できる。 
new Integer(String).intValue()変換は出来るが、効率は最悪
なお、new Integer()はJava9から非推奨。
2021-03-21
Integer.parseInt(String, 16)十六進数を数値に変換する。全角文字も変換できる。2021-09-19
HexFormat.fromHexDigits(String)十六進数を数値に変換する(Java17以降)。2021-09-19
IntegerStringInteger n=Integer.decode(String)「0x」「#」から始まると十六進数として認識してくれる。2007-12-29
StringintString s=Integer.toString(int)  
String#valueOf(int)内部ではInteger#toString(int, 10)を呼んでいる。 
"" +intJavaScriptでは常套手段だが、JavaではStringBuilderが余計に作られるのでいまいち。2008-05-22
String.format("%d",int)JDK1.5以降。0埋めや桁数指定("%04d")が出来る。2008-05-21
"%d".formatted(int)Java15以降。2023-09-23
Integer.toBinaryString(int)二進数 
Integer.toOctalString(int)八進数 
String.format("%o",int)八進数(JDK1.5以降)。0埋めや桁数指定("%04o")が出来る。2008-05-21
Integer.toHexString(int)十六進数。0埋めはString s = Integer.toHexString(b);if (b.length < 2) s = "0" + s;とか2008-07-05
String.format("%x",int)十六進数(JDK1.5以降)。0埋めや桁数指定("%04x")が出来る。2008-05-21
HexFormat.of().toHexDigits(int)十六進数(Java17以降)。桁数は8桁固定。2021-09-19
HexFormat.of().toHexDigits(long, intketa)十六進数(Java17以降)。第2引数で桁数を指定。2021-09-19
Integer.toString(int, intn)n進数に対応。進数nは正の数のみ 
StringdoubleString s=Double.toString(double)
// Java18jshell> Double.toString(2e23)$1 ==> "1.9999999999999998E23"
// Java19jshell> Double.toString(2e23)$1 ==> "2.0E23"
2023-09-23
String.format("%e",double)
jshell> String.format("%e", 2e23)$1 ==> "2.000000e+23"
2023-09-23
// Java20jshell> String.format("%.16e", 2e23)$2 ==> "1.9999999999999998e+23"
// Java21jshell> String.format("%.16e", 2e23)$2 ==> "2.0000000000000000e+23"
2023-09-23
String.format("%f",double)
// Java20jshell> String.format("%f", 2e23)$1 ==> "199999999999999980000000.000000"
// Java21jshell> String.format("%f", 2e23)$1 ==> "200000000000000000000000.000000"
2023-09-23
"%f".formatted(double)Java15以降。 
IntegerintInteger n=new Integer(int)(JDK1.5以降では)-128〜127なら、valueOf()の方が(キャッシュされているので)メモリ使用効率は良い。
Java9で非推奨になった。
JDK1.5からは直接代入が出来るようになった。2021-03-21
Integer.valueOf(int)JDK1.5以降で使用可能。2007-05-02
intIntegerint i=IntegerObj.intValue()  
booleanStringboolean b=Boolean.parseBoolean(String)JDK1.5以降2009-12-31
BooleanStringBoolean b=Boolean.valueOf(String) 2009-12-31
BooleanbooleanBoolean b=Boolean.valueOf(boolean)JDK1.4以降(定数ならBoolean.TRUEBoolean.FALSEを使うのがいい)2009-12-31
DateString   日付(Date)⇔文字列(String)の変換 
StringDate    

※Boolean.getBoolean()やInteger.getInteger()は、変換用ではなく、システムプロパティーの取得用。[2009-12-31]

十六進数文字⇔数値変換[2007-01-12]

char c =Character.forDigit(10, 16);  // 'a'が返るint  n =Character.digit('a', 16);    // 10が返るint  n =HexFormat.fromHexDigit('a'); // 10が返る(Java17以降)[2021-09-19]

数字判断[2007-01-12]

System.out.println(c + ":" +Character.isDigit(c) + "/" +Character.digit(c,16));
0:true/01:true/1a:false/101:true/1…全角数字も数字と判断されるし、数値変換も正しく行われる一:false/-1…さすがに漢数字等は無理(苦笑)壱:false/-1�T:false/-1�@:false/-1字:false/-1

HexFormat.isHexDigit(c)(Java17以降)[2021-09-19]

半角カタカナ⇔全角カタカナ⇔全角ひらがな変換


自動ボクシング

プリミティブ型ラッパークラスは別物なのでお互いに直接代入することは出来ないが、JDK1.5からは出来るようになった。[2007-05-02]
これを自動ボクシング(オートボクシング:AutoBoxing)と呼ぶ。
→Sunのオートボクシング

Integer i = 123;//オートボクシング(ボクシング変換:boxing conversion)int j = i;//オートアンボクシング(アンボクシング変換:unboxing conversion)

(コンパイルする際にはソースのレベルを1.5以上にする必要がある)

コンパイルしたものを逆コンパイルして見ると、ただ単に変換メソッドに置き換えられているだけ…。

Integer i =Integer.valueOf(123);int j = i.intValue();

なので、コーディング上は便利だけど、実行効率的には気をつけた方が良さげ。

プログラミング上も、オーバーロードされているメソッドで引数の違いがintとObjectだった場合とかは、どちらのメソッドが呼ばれるか気をつけなきゃいけないだろうな。

Integer i = 123;System.out.println(i);//引数がObject型のprintln()が呼ばれる

Objectクラスとの自動ボクシング

ちなみに、プリミティブ型からObjectクラスへのボクシングも勝手にやってくれるが、Objectからプリミティブ型への変換は やってくれない。[2007-05-10]

Object obj = 123;//OK(実体はIntegerのインスタンス)int i = obj;//コンパイルエラー

intへ変換するintValue()とかlongへ変換するlongValue()とかは、実は“IntegerやLongの親クラスであるNumberクラス”のメソッドなので、「int i = ((Number)o).intValue();」とかに変換してコンパイルすることは出来るはず。
だが、実体がNumberの派生クラスでない場合は実行時エラーになる(実行してみるまで分からない)ので、コンパイルエラーにしておくのが無難なのかな。
(nullだと実行時にNullPointerExceptionが起きるらしいが)

Integerであることが分かっているなら、キャストしておけばコンパイルエラーは消せる。[2008-07-21]

Object obj = 123;int i = (Integer)obj;//OK//×int i = (Number)obj;//Numberからintへ変換できないというコンパイルエラー//×long l = (Long)obj;//コンパイルエラーにはならないが、実行時にClassCastException(Integer→Longは×)

使用上の注意

プリミティブ同士なら==演算子で比較するが、オートボクシングで変換されればラッパークラスというオブジェクト(参照型)になるので、==で比較するなんて、もっての他。[2008-05-21]

public static void main(String[] args) {{System.out.print(127);Integer i1 = 127;Integer i2 = 127;if (i1 == i2) {System.out.println("は等しい");} else {System.out.println("は異なる");}}{System.out.print(128);Integer i1 = 128;Integer i2 = 128;if (i1 == i2) {System.out.println("は等しい");} else {System.out.println("は異なる");}}}

実行結果:

127は等しい128は異なる

何で結果が違うかというと、intからIntegerへは「new Integer()」でなく「Integer.valueOf()」が使われるから。
これは(現状では)-128〜127の範囲ではキャッシュされたIntegerを返すようになっているので、その範囲なら同一のインスタンスとなる。だから==で比較しても等しくなる。
しかしその範囲外だとnewで作るので、==では一致しない

そういうわけで現状は-128〜127の範囲なら大丈夫かもしれないが、将来バージョンで変わっても不思議は無いので、==を使うべきではない。
というかクラス(Integer)が明示的に現れているんだから、そもそも==で比較しようとすんなやって話。

Java言語仕様第3版5.1.7章の中で「-128〜127」と書かれているので、その範囲が狭くなることは無いと思うが。[2008-08-30]


逆のオートアンボクシングでは、ラッパークラス側がnullにならないように注意。[2008-05-21]
nullだと実行時にNullPointerExceptionが発生してしてしまう。

Integer n = null;int i = n;//NullPointerException
Map<String, Integer> map = new HashMap<String, Integer>();int i = map.get("zzz");//NullPointerException
Integer n = null;n++;//NullPointerException

Integer nに対するn++は、実際には「int temp = n.intValue(); temp++; n = Integer.valueOf(temp);」という感じに変換されている。
ループのカウンターとかに使ったら、えらくムダだな…。


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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


[8]ページ先頭

©2009-2025 Movatter.jp