他のプログラミング言語と同様に、Javaにもデータ型が存在します。
Java超入門の第2回では、プリミティブ型の説明を行わせていただきます。
「Java超入門の第1回」も是非ご覧ください。
本エントリーの内容は以下の通りです。
- プリミティブ型とは
- プリミティブ型に含まれる型
- プリミティブ型における自動型変換とキャスト処理
- Javaで利用できる演算子
- Javaで計算式を書く時の注意点
1 プリミティブ型とは
プリミティブ型は、基本データ型や基本型などと表現されることもあります。
では、それ以外の型は?、と思われる方が多いと思います。それは参照型(オブジェクト型)です。
簡単にこの2つの型の違いをイメージ(あくまでもイメージです。)で説明すると、以下の図のようになります。
まだ変数の説明ができていませんが、変数とは段ボール箱1つに相当するとお考えください。
上図に書いているままですが、 段ボールA(変数A)にはプリミティブ型の数値(例えば1円玉が1000枚)が入っています。
段ボールB(変数B)には参照型のアドレスが入っています。もっと端的に例えると、住所が書かれたメモが入っていて、
そこに行くと何かが置いてある。 みたいな感じです。
2 プリミティブ型に含まれる型
プリミティブ型には以下の型が含まれます。
論理値型
真偽値を格納する型です。
型 | サイズ(ビット) | 説明 |
---|---|---|
boolean | 1 | falseまたはtrue |
文字型
型 | サイズ(ビット) | 説明 |
---|---|---|
char | 16 | Unicode規格の文字コード(\u0000から\uFFFF) |
数値型
型 | サイズ(ビット) | 説明 |
---|---|---|
byte | 8 | 符号つき整数(-128から127) |
short | 16 | 符号つき整数(-32768から32767) |
int | 32 | 符号つき整数(-2147483648から2147483647) |
long | 64 | 符号つき整数(-9223372036854775808から9223372036854775807) |
float | 32 | 4バイト浮動小数点数 |
double | 64 | 8バイト浮動小数点数 |
プリミティブ型の利用例
プリミティブ型にどんな型があるかは理解していただけたと思いますが、
実際に利用してみないと、ピントこないと思いますので、すこし利用してみます。
Java超入門の1回目の
終盤の「プロジェクトの作成と簡単なプログラムの作成」で作成(と言える程ではないですが・・・)
したsampleプロジェクトのHelloWorld.javaにコードを追記してみます。
「変数」という言葉がページの前半の内容でも出現しているとは思います。
「変数」の説明は、Java超入門の3回目以降で行う予定ですので、ここでは名前の付いた箱ぐらいに考えてください。
プリミティブ型の箱の作るには
箱の型名 箱の名前 = 箱に入れる値;
との記載が必要です。
イコールの右側の「箱に入れる値」は絶対に必要な物ではないですが、 今回はこの形だけを利用します。
では実際にプリミティブ型の箱をプログラム中に作ってみましょう! 箱を作る前のプログラム(1回目で作成した物)は以下の通りです。
1 2 3 4 5 6 7 8 |
package sample; public class HelloWorld { public static void main (String[] args) { String helloWorldStr = "Hello World !!"; System.out.println(helloWorldStr); } } |
boolean型の利用例
booleanの変数(変数名:boolValue)の宣言を追加しました。
実際の変数名としてはイマイチな名前ですね・・・
1 2 3 4 5 6 7 8 9 10 |
package sample; public class HelloWorld { public static void main (String[] args) { //booleanの変数boolValueを宣言してtrueで初期化 boolean boolValue = true; String helloWorldStr = "Hello World !!"; System.out.println(helloWorldStr); } } |
int型の利用例
booleanと同じ様に、int型の変数(変数名:intValue)の宣言を追加しましたが
右辺には、10+20との式を指定しました。
1 2 3 4 5 6 7 8 9 10 11 12 |
package sample; public class HelloWorld { public static void main (String[] args) { //booleanの変数boolValueを宣言してtrueで初期化 boolean boolValue = true; //intの変数intValueを宣言して10+20で初期化 int intValue = 10 + 20; String helloWorldStr = "Hello World !!"; System.out.println(helloWorldStr); } } |
Eclipseでデバッグして確認
確認しなくてもintValueの値は30であるはずですね。
System.out.printでコンソールに出力して確認するのが手っ取り早いのですが、
敢えてEclipseのデバッグ機能で確認してみます。
デバッグ実行するだけでは、デバッグモードで実行されるだけで、直ぐ終了してしまい
intValueの値が確認できませんので、途中で止まるようにブレークポイントの指定が必要となります。
・ブレークポイントの指定
以下の画像の要領でブレークポイントを指定します。
ブレークポイントを指定して、プログラムをデバッグ実行すると、
ブレークポイント指定行に処理が到達すると自動的に処理が中断されます。
ブレークポイントの指定後の画面は以下の様になります。 対象行に、青丸のブレークポイントが設定されていることが見て取れます。
・デバッグ実行
デバッグ実行の起動方法は何通りかあるのですが、一番オーソドックスと私が思っている方法でやってみます。
操作方法は、パッケージ・エクスプローラーでHelloWorldクラスを選択後に右クリックメニューを表示し、
[デバッグ]>[Javaアプリケーション]を選択します。
これでデバッグが始まると思いきや、HelloWorld.javaをセーブしていなかったので、
以下の確認画面が表示されますので、「ok」ボタンをクリックしてください。
これでデバッグが始まると思いきや、今度は以下の画面が表示されました。
デバッグ・パースペクティブを開いてもよいかの確認ですので、「はい」ボタンをクリックしてください。
なお、Eclipseの設定によってはこの確認ダイアログは表示されない場合があります。
三度目の正直ですね、デバッグが開始されて、指定したブレークポイントの行で処理が中断しました。
この「変数ビュー」の中身を見てみるとintValueが有ります。やはり値は30となっています。
・「変数ビュー」の表示
「変数ビュー」の表示位置はEclipseの設定によって変わりますし、非表示になっている場合があります。
表示されていない場合は、Eclipseのメニューの[ウィンドウ]>[ビューの表示]>「変数」をクリックし表示してください。
以下の画像はMacの物ですが、Windowsでは、メニューがEclipseに直に付いているだけの違いです。
・デバッグ実行の停止とパースペクティブの切り替え
intValueの確認も終わったので、以下の画像の赤枠部分をクリックして、デバッグ実行を停止してください。
デバッグ実行時に「デバッグ・パースペクティブ」に切り替わっていると思いますので
パースペクティブの切り替えも行います。以下の画像の赤枠部分をクリックすると切り替わります。
long型の利用例
boolean、intと同じようにlongの変数(変数名:longValue)の宣言を追加しました。
右辺の値には100を指定しました。 以降では、ソースは宣言行だけを記載させていただきます。
1 2 |
//longの変数longValueを宣言して100で初期化 long longValue = 100; |
実は、上記のソースには潜在的な問題が潜んでいます。 Eclipse上では特に問題は発生していません。
些細な問題として、追加した3つの変数がどこにも使われていないとの警告は出ていますが、
本エントリーでは、気にしなくても良いレベルの問題です。
潜んでいる問題を明確するために、右辺の値を100からlongの最大値に変更します。
1 |
long longValue = 9223372036854775807; |
画像でも確認できるとは思いますが、エラー内容は以下のようになっています。
型 int のリテラル 9223372036854775807 は範囲外です
リテラルとは、データをソースコードの中で表現したものです。
変数の宣言時にイコールで任意の数値を指定する場合、その任意の数値をリテラルと表現します。
エラー内容に戻りますが、 longの変数longValueに値を代入しているのに、9223372036854775807はintの範囲外と言われています。
何故この様になるかというと、Javaの整数の数値リテラルは、デフォルトでintとして扱われるからです。
デフォルトのintで扱われないためには、整数の数値リテラルの最後にLまたはlを付与し、値がlongであることを宣言します。
これで先ほどのコンパイルエラーが無くなりました。
1 |
long longValue = 9223372036854775807l; |
同様の問題がfloat型の変数の初期化時にも発生します。
浮動小数点数型の数値リテラルはデフォルトでdouble型として扱われます。
浮動小数点数型の数値リテラルの最後にFまたはfを付与することで、値がfloatであることを宣言できます。
3 プリミティブ型における自動型変換とキャスト処理
先ほどの章では、整数の数値リテラルがintとして扱われることを説明させていただきましたが、
ではなぜ
1 2 |
//longの変数longValueを宣言して100で初期化 long longValue = 100; |
はコンパイルエラーとならないのでしょうか?
エラーとならい理由を説明するために「拡張型変換」、「縮小型変換」を説明させていただきます。
拡張型変換
拡張型変換とは、サイズの小さい型を大きい型に代入する時の変換を意味します。
この場合、代入先の箱(型)が大きいので、自動的に型変換されます。
この仕組みによってintの数値リテラルが、自動的にlongに型変換され
long longValue = 100 がコンパイルエラーとならないことが説明できます。
型の自動変換は、参照型でも発生します。この点については第3回以降で説明させていただきます。
縮小型変換
サイズの大きな型を小さい型に代入するときは、演算精度の低下が起こる可能性が発生するため、自動的に型変換はされません。
この変換を行うためには明示的な型変換を行うキャスト処理が必要です。
キャスト処理
縮小型変換の箇所で説明した明示的な型変換処理です。
intの変数に、longのサイズの数値リテラルを代入するコード例は以下の通りです。
言わずもがなですが、この例はやってはいけない処理の例です。
1 |
int castSample = (int)9223372036854775807L; |
デバッグ実行してcastSampleの値がどうなるか確認してみたところ、値が-1になりました。
キャストしても問題無い例のコードは以下の通りです。
1 |
int castSample = (int)1000L; |
念のため、デバッグ実行してcastSampleの値がどうなるか確認してみたところ、値が1000になりました。予想通りです。
4 Javaで利用できる演算子
と思ったのですが、 http://msugai.fc2web.com/java/ope.htmlのページが非常に良くまとまっておりますので こちらをご参照ください。
5 Javaで計算式を書く時の注意点
計算式を書き、実行すると思わぬ結果になることがあります。その時点で気付ければ問題ないですよね・・・
これはJavaの仕様の不理解により発生する問題です。
自己学習をしている時に、この問題に気付けばいいのですが、実際のコードを書いてテストでも検出されず、
お客さんから金額が合わない、なんて問い合わせを受けるのは避けたいものです。
問題が発生する経緯
消費税(8%)を計算する処理を例とします。 計算式は何通りか考えられますね。品物の値段をXとすると
- X * 0.08
- x / 100 * 8
- X * 8 / 100
ぐらいが一般的な答えの候補だと思います。
問題が発生しないXの時
Xが1000円の場合は、上記の3式ともに答えは80円になり、問題は発生しません。
実際の計算式のコードは以下の様になります。
1 2 3 4 5 6 |
//式1: 1000 * 0.08 float taxValue1 = 1000 * 0.08f; //式2: 1000 / 100 * 8 float taxValue2 = 1000 / 100 * 8; //式3: 1000 * 8 / 100 float taxValue3 = 1000 * 8 / 100; |
問題が発生するXの時
Xが100,250円の場合は式2で問題が発生します。
実際の計算式のコードは以下の様になります。
1 2 3 4 5 6 |
//式1: 100250 * 0.08 float taxValue1 = 100250 * 0.08f; //式2: 100250 / 100 * 8 float taxValue2 = 100250 / 100 * 8; //式3: 100250 * 8 / 1000 float taxValue3 = 100250 * 8 / 100; |
デバッグ実行で確認した値は式1、式3は8020、式2は8016になりました。
何故結果が異なるかについての説明をさせていただきます。
式1と式3は特筆すべき点は有りません。
式1: 100250 * 0.08 = 8020
式3: 100250 * 8 / 100 = 8020
問題の式2です。四則計算の法則によりまず
100250 / 100の計算が行われます。
人間や一般的な計算機が計算すると
100250 / 100 = 1002.5 との結果が出ます。しかしJava VMが計算すると
100250 / 100 = 1002 となってしまいます。理由はintをintで割ると、答えもintになる仕様だからで、小数点以下の数値0.5が切り捨てられてしまいます。
再度この動きを式で表すと以下の様になります。
式2: 100250 / 100 * 8 = 1002 * 8 = 8016
式2利用時でもXの最後にfを付与して、Xがfloatであることを明示すれば正しい結果となります。
正しい結果になる理由はfloatをintで割ると、答えはfloatになる仕様だからです。
intをfloatで割っても答えはfloatになります。
以下に、各数値型を四則演算した時の結果の型を示します。
数値1(型) * 数値2(型) = 結果の型を表した表となります。この例はかけ算の例となります。
なお、四則演算全ての結果は同じ型となりますので、表の列に演算子は存在しておりません。
数値1 | 数値2 | 結果の型 |
---|---|---|
int | int | int |
int | float | float |
int | long | long |
int | double | double |
float | long | float |
float | double | double |
long | double | double |
見ていただいて分かる通り、数値の精度が落ちない結果型になることが見て取れます。
この法則を念頭に置いて、計算式を構成するとお金の計算(それ以外の数値もですが)で不要なバグを出さずにすみます。
関連記事
-
-
Mac(OS X)におけるJava8(jdk8)等のインストール、アップデート、アンインストール方法
Windowsとは異なりMac(OS X)ではJDKの管理(インストール、アンインストール)が難しい
-
-
Selenium利用時のトラブルシューティング方法[クリック編]
Seleniumは便利なテスト自動化ツールですし、今後は更なる利用者の増加が見込まれます。 とは言
-
-
Eclipse4.4(Java)における自動ビルド設定の変更方法の説明
Eclipse4.4における自動ビルド設定の変更方法を説明させていただきます。 自動ビルド設定の変
-
-
Eclipse4.3のチュートリアル機能で”Hello World”アプリケーションの作成方法を説明する。
Eclipseのインストールが終了したので、各画面エリアの名称の説明、各画面エリアの使い方の説明を
-
-
JDK8(Java8)のインストール方法[Windows]
本エントリーは、Windows7 64bitにJDK8(Java8)をインストールする説明を記載させ
-
-
Java超入門 with Eclipse[3:クラスに関する基礎知識(クラスとインスタンスとパッケージ)]
Javaといえば、「オブジェクト指向」とのイメージがとっても強いですよね。 そう、そうです。間違い
-
-
java8(JDK8)の新機能[大幅に強化されたコレクションAPI:java.util.List] をeclipseとJUnitで確認する。
Java8(JDK8)では、ラムダ式の導入を前提とした、コレクションAPIの新機能が追加されました。
-
-
Eclipse4.4,4.3の使い方[エディタのフォントサイズの変更方法]
今回は、Eclipse4.4と,4.3におけるエディタエリアのフォントサイズの変更方法を説明させてい
-
-
Java8の新機能に完全対応のEclipseメジャーリリースとなる Eclipse 4.4 Luna (ルナ) が遂にリリース
Eclipse メジャーリリースとなる Eclipse 4.4 Luna (ルナ) が遂にリリースさ
-
-
Selenium入門その3[Selenium WebDriver(Java/Junit4)の使い方]
WebDriverでは、予め中継サーバを起動しなくても、テスト実行時にブラウザ拡張機能や、OSのネイ