データ型 ( data type )とは、データの種類のことです。 これまでに、整数と実数の2種類のデータを扱ってきました。 また、配列というデータも利用しました。 Javaには、この他のデータ型も用意されています。
Javaのデータ型は、まず、基本データ型と参照データ型の2つに大きく分類されます。 基本データ型 ( primitive data type )には、整数型、浮動小数点数型、論理型、および文字型があります。 参照データ型 ( reference data type )には、クラス型と配列型があります。 (クラス型については次回説明します。)
以下は、基本データ型の詳細です。
種類 | 型名 | ビット | 説明 |
---|---|---|---|
整数型 | byte型 | 8 | −2 7 (−128)〜2 7 −1(127) |
整数型 | short型 | 16 | −2 15 (−32768)〜2 15 −1(32767) |
整数型 | int型 | 32 | −2 31 〜2 31 −1(9桁程度) |
整数型 | long型 | 64 | −2 63 〜2 63 −1(18桁程度) |
浮動小数点数型 | float型 | 32 | 指数+38〜−45, 有効桁数7桁程度 |
浮動小数点数型 | double型 | 64 | 指数+308〜−324, 有効桁数14桁程度 |
論理型 | boolean型 | - | trueまたはfalse |
文字型 | char型 | 16 | \u0000(0)〜\uFFFF(65535) |
コンピュータのデータは、究極的には0と1です。 この0と1を、 ビット ( bit )と呼びます。 8桁のビットを バイト ( byte )と呼びます。 現在のコンピュータは、バイトを基本単位としています。 基本データ型が8ビット単位であるのは、ここに理由があります。
整数を扱う場合、普通はint型を用います。 ただし、int型は9桁程度が限界であり、これを超えると意味のない計算をしてしまいます。 int型の範囲を超えるような大きい数を扱うときには、long型を用います。
今まで、実数と呼んできたものは、正確に言うと浮動小数点数です。 浮動小数点数 ( floating point number )とは、小数点をずらすことによって、非常に大きな数や非常に小さな数も表現できるようにした実数のことです。 浮動小数点数を扱う場合、普通はdouble型を用います。 限られたビット数で表現する以上、小数点をずらす桁数には限度がありますし、小数の精度にも限界があります。
Javaには、物事の真偽を表すデータもあります。 正しいことや条件が成り立つことが真で、記号trueで表されます。 間違っていることや条件が成り立たないことが偽で、記号falseで表されます。 このtrueとfalseを 真理値 ( truth value )または 論理値 ( logical value )、 ブール値 ( Boolean value )と呼びます。
論理型 ( logical type )とは、真理値を表すデータ型です。 Javaでは、boolean型が論理型です。
if文の条件式のように、値が論理型である式を、 ブール式 ( Boolean expression )と呼びます。 これまで「条件が成り立つ」とか「条件が成り立たない」と言ってきたことは、正確には、ブール式の値がtrueやfalseになることです。
注意: Jave以外のプログラミング言語では、trueとfalseを1と0で代用しているものがありますが、Javaで真理値として1や0を使うとエラーになります。
コンピュータにとっては、整数や実数だけでなく、文字も立派なデータです。 もし、文字を1バイトで表現すると、256種類が限界となります。 2バイトなら、65536種類の文字が表現可能です。
Javaは、文字(char型)を1バイトではなく2バイトで表現します。 したがって、アルファベットだけでなく、漢字などもデータとして扱えます。
なお、ちょうど1バイトで表現されるデータ型として、byte型が用意されています。
文字は、コンピュータの中では整数として処理されます。 この、文字から整数への対応を 文字符号 ( character code )と呼びます。
Javaが採用している文字符号はUnicodeです。 このUnicodeを理解するには、その前にASCIIを理解する必要があります。 ASCII (アスキー)は、アメリカで制定された文字符号です。 ASCIIでは、数字、アルファベット、記号などに符号が割り当てられています。 そして、 Unicode (ユニコード)は、ASCIIを元にして、世界中の文字を追加した文字符号です。 Unicodeでは、漢字などにも符号が割り当てられています。
主な文字のASCII符号は次の通りです。
文字 | 符号 |
|
文字 | 符号 |
|
文字 | 符号 |
|
文字 | 符号 |
|
文字 | 符号 |
|
文字 | 符号 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
0 | 48 | @ | 64 | P | 80 | ` | 96 | p | 112 | |||||
! | 33 | 1 | 49 | A | 65 | Q | 81 | a | 97 | q | 113 | |||||
" | 34 | 2 | 50 | B | 66 | R | 82 | b | 98 | r | 114 | |||||
# | 35 | 3 | 51 | C | 67 | S | 83 | c | 99 | s | 115 | |||||
$ | 36 | 4 | 52 | D | 68 | T | 84 | d | 100 | t | 116 | |||||
% | 37 | 5 | 53 | E | 69 | U | 85 | e | 101 | u | 117 | |||||
& | 38 | 6 | 54 | F | 70 | V | 86 | f | 102 | v | 118 | |||||
' | 39 | 7 | 55 | G | 71 | W | 87 | g | 103 | w | 119 | |||||
( | 40 | 8 | 56 | H | 72 | X | 88 | h | 104 | x | 120 | |||||
) | 41 | 9 | 57 | I | 73 | Y | 89 | i | 105 | y | 121 | |||||
* | 42 | : | 58 | J | 74 | Z | 90 | j | 106 | z | 122 | |||||
+ | 43 | ; | 59 | K | 75 | [ | 91 | k | 107 | { | 123 | |||||
, | 44 | < | 60 | L | 76 | \ | 92 | l | 108 | | | 124 | |||||
- | 45 | = | 61 | M | 77 | ] | 93 | m | 109 | } | 125 | |||||
. | 46 | > | 62 | N | 78 | ^ | 94 | n | 110 | ~ | 126 | |||||
/ | 47 | ? | 63 | O | 79 | _ | 95 | o | 111 |
|
|
変数は、宣言すれば使えます。 しかし、どこでも使えるわけではありません。 変数が使えるのは、ある一定の範囲内です。 変数の使える範囲を、変数の スコープ ( scope )と呼びます。
前回、メソッド定義の中で変数を宣言しました。 メソッド定義の中で宣言した変数は、そのメソッド定義の中でしか使えません。 呼び出し側は、 main というメソッドの定義と見なせます。 したがって、呼び出し側の中で宣言した変数も、呼び出し側の中でしか使えません。
次の例では、メソッド main で変数 x , メソッド test で変数 y を宣言しています。 メソッド main では、 main の x は使えますが、 test の y は使えません。 メソッド test では、 test の y は使えますが、 main の x は使えません。
/* 1*/ class VariableScope1 { // 変数のスコープ1 /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; // xを宣言 /* 4*/ test(); /* 5*/ System.out.println("main x = " + x); /* 6*/ // testのyは使えない /* 7*/ } /* 8*/ static void test () { /* 9*/ int y = 200; // yを宣言 /* 10*/ System.out.println("test y = " + y); /* 11*/ // mainのxは使えない /* 12*/ } /* 13*/ }
24102a1:java1 k16x1001$ java VariableScope1 test y = 200 main x = 100 24102a1:java1 k16x1001$
では、呼び出し側とメソッド定義の間でデータを交換するには、どうしたらよいでしょう。 正解は、引数と返り値を使う、です。 呼び出し側からメソッド定義にデータを伝えるには、引数を使います。 メソッド定義から呼び出し側にデータを伝えるには、返り値を使います。
次の例では、メソッド main の x の値をメソッド test に伝えるために、引数を使って、その値を x2 に格納しています。 また、メソッド test の y の値をメソッド main に伝えるために、返り値を使って、その値を y2 に格納しています。
/* 1*/ class VariableScope2 { // 変数のスコープ2 /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100, y2; /* 4*/ y2 = test(x); // testのyをy2に格納 /* 5*/ System.out.println("test y = " + y2); /* 6*/ } /* 7*/ static int test (int x2) { // mainのxをx2に格納 /* 8*/ int y = 200; /* 9*/ System.out.println("main x = " + x2); /* 10*/ return y; /* 11*/ } /* 12*/ }
24102a1:java1 k16x1001$ java VariableScope2 main x = 100 test y = 200 24102a1:java1 k16x1001$
さて、呼び出し側とメソッド定義で同じ名前の変数を宣言しても、それらは別の変数と見なされます。
次の例では、メソッド main とメソッド test の両方で、変数 x を宣言しています。 メソッド main で x に100を格納し、メソッド test で x の値を200に変更しているように見えます。 しかし、 main の x の値は100のままです。 メソッド test では、 main の x でなく、 test の x に200を格納したのです。
/* 1*/ class VariableScope3 { // 変数のスコープ3 /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ test(); // xは変わらない /* 5*/ System.out.println("main x = " + x); /* 6*/ } /* 7*/ static void test () { /* 8*/ int x = 200; // testのxに格納したから /* 9*/ System.out.println("test x = " + x); /* 10*/ } /* 11*/ }
24102a1:java1 k16x1001$ java VariableScope3 test x = 200 main x = 100 24102a1:java1 k16x1001$
どうしても、呼び出し側とメソッド定義で同じ変数を使いたい場合は、
クラス変数
(
class variable
)というものを使います。
これは、
class
の直下で宣言する変数で、
static int 変数;
などと書きます。 クラス変数は、呼び出し側でもメソッド定義でも同じ変数と見なされます。
次の例では、クラス変数 x を宣言しています。 メソッド main で x に100を格納し、メソッド test で x の値を200に変更します。 今度は、 main でも test でも、 x の値は200になります。
/* 1*/ class VariableScope4 { // 変数のスコープ4 /* 2*/ static int x; // mainでもtestでも使える /* 3*/ public static void main (String[] args) { /* 4*/ x = 100; /* 5*/ test(); // xは変わる /* 6*/ System.out.println("main x = " + x); /* 7*/ } /* 8*/ static void test () { /* 9*/ x = 200; // クラス変数xに格納したから /* 10*/ System.out.println("test x = " + x); /* 11*/ } /* 12*/ }
24102a1:java1 k16x1001$ java VariableScope4 test x = 200 main x = 200 24102a1:java1 k16x1001$
これまでに扱ったメソッドは、値を返さないか、整数や実数を返すものでした。 その他のメソッドとして、真理値を返すものが考えられます。 真理値を返すメソッドは、 ブール値メソッド ( Boolean-valued mothod )と呼ばれます。 ブール値メソッドは、if文の条件式をメソッドにまとめるときなどに使われます。
例えば、生年月日と今日の日付を入力して、今日が誕生日かどうかを判定する問題を考えます。
日付をどのようにデータにするかは、いくつか方法がありますが、ここでは8桁形式を利用します。 つまり、2016年12月1日を整数20161201で表します。 日付の8桁形式には、次のような利点があります。
日付の8桁形式の欠点は、以下のとおりです。
さて、日付の8桁形式を利用して誕生日を判定するには、生年月日の下4桁と今日の日付の下4桁が一致すればよいです。 8桁形式の下4桁は、10000で割った余りで取り出せます。 この条件判定をプログラムで行うと、次のようになります。
/* 1*/ import java.io.*; /* 2*/ /* 3*/ class Birthday1 { // 誕生日1 /* 4*/ public static void main (String[] args) throws IOException { /* 5*/ InputStreamReader isr = new InputStreamReader(System.in); /* 6*/ BufferedReader br = new BufferedReader(isr); /* 7*/ int birth, today; /* 8*/ System.out.print("生年月日を8桁形式で入力してください: "); /* 9*/ birth = Integer.parseInt(br.readLine()); /* 10*/ System.out.print("今日の日付を8桁形式で入力してください: "); /* 11*/ today = Integer.parseInt(br.readLine()); /* 12*/ if (birth % 10000 == today % 10000) { // ここをメソッドにする /* 13*/ System.out.println("今日は誕生日です。"); /* 14*/ } else { /* 15*/ System.out.println("今日は誕生日ではありません。"); /* 16*/ } /* 17*/ } /* 18*/ }
24102a1:java1 k16x1001$ java Birthday1 生年月日を8桁形式で入力してください: 19961216 今日の日付を8桁形式で入力してください: 20161216 今日は誕生日です。 24102a1:java1 k16x1001$ java Birthday1 生年月日を8桁形式で入力してください: 19961217 今日の日付を8桁形式で入力してください: 20161216 今日は誕生日ではありません。 24102a1:java1 k16x1001$
このプログラムのif文の条件式をメソッドにまとめます。 このメソッドは、条件に合うか合わないかを判定するものなので、真理値を返す、すなわちブール値メソッドになります。 メソッドの名前は isBirthday とします。
メソッド定義では、真理値を返すので、
static boolean
と指定します。
そして、条件式の値を
return
で返します。
プログラムは次の通りです。
/* 1*/ import java.io.*; /* 2*/ /* 3*/ class Birthday2 { // 誕生日2 /* 4*/ public static void main (String[] args) throws IOException { /* 5*/ InputStreamReader isr = new InputStreamReader(System.in); /* 6*/ BufferedReader br = new BufferedReader(isr); /* 7*/ int birth, today; /* 8*/ System.out.print("生年月日を8桁形式で入力してください: "); /* 9*/ birth = Integer.parseInt(br.readLine()); /* 10*/ System.out.print("今日の日付を8桁形式で入力してください: "); /* 11*/ today = Integer.parseInt(br.readLine()); /* 12*/ if (isBirthday(birth, today)) { // ブール値メソッド呼出し /* 13*/ System.out.println("今日は誕生日です。"); /* 14*/ } else { /* 15*/ System.out.println("今日は誕生日ではありません。"); /* 16*/ } /* 17*/ } /* 18*/ static boolean isBirthday (int birth, int today) { // ブール値メソッド定義 /* 19*/ return birth % 10000 == today % 10000; // 真理値を返す /* 20*/ } /* 21*/ }
生年月日を入力すると、21世紀生まれかどうかを判定するプログラムを作成してください。 条件判定にはブール値メソッドを使うこととします。
メソッドの名前は
isBornIn21C
とします。
このメソッドの引数は、整数
birth
です。
このメソッドは真理値を返すので、
static boolean
と指定します。
メソッド定義では、
birth
が2001年1月1日以降という条件式の値を
return
で返します。
24102a1:java1 k16x1001$ java BirthAge 生年月日を8桁形式で入力してください: 20010101 21世紀生まれです。 24102a1:java1 k16x1001$ java BirthAge 生年月日を8桁形式で入力してください: 20001231 21世紀生まれではありません。 24102a1:java1 k16x1001$
余力のある人は、今日の日付も入力するようにし、成人(20才以上)を判定するブール値メソッド isAdult も定義し、これを呼び出して、成人かどうかの判定もしてください。
24102a1:java1 k16x1001$ java BirthAge2 生年月日を8桁形式で入力してください: 19961216 今日の日付を8桁形式で入力してください: 20161216 21世紀生まれではありません。 成人です。 24102a1:java1 k16x1001$ java BirthAge2 生年月日を8桁形式で入力してください: 19961217 今日の日付を8桁形式で入力してください: 20161216 21世紀生まれではありません。 成人ではありません。 24102a1:java1 k16x1001$
今日の演習12の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(12月16日)を明記してください。