[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理技法(Javaプログラミング)I 第11回

目次
索引

データ型

データ型とは

データ型 data type )とは、データの種類のことです。 これまでに、整数と実数の2種類のデータを扱ってきました。 また、配列というデータも利用しました。 Javaには、この他のデータ型も用意されています。

Javaのデータ型は、まず、基本データ型と参照データ型の2つに大きく分類されます。 基本データ型 primitive data type )には、整数型、浮動小数点数型、論理型、および文字型があります。 参照データ型 reference data type )には、クラス型と配列型があります。 (クラス型については次回説明します。)

以下は、基本データ型の詳細です。

Javaの基本データ型
種類 型名 ビット 説明
整数型 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符号は次の通りです。

主な文字の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 は使えません。

VariableScope1.java
/*  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*/ }
コンソール
test y = 200
main x = 100

Completed with exit code: 0
変数のスコープのイメージ(1)
変数のスコープのイメージ(1)

では、呼び出し側とメソッド定義の間でデータを交換するには、どうしたらよいでしょう。 正解は、引数と返り値を使う、です。 呼び出し側からメソッド定義にデータを伝えるには、引数を使います。 メソッド定義から呼び出し側にデータを伝えるには、返り値を使います。

次の例では、メソッド main x の値をメソッド test に伝えるために、引数を使って、その値を x2 に格納しています。 また、メソッド test y の値をメソッド main に伝えるために、返り値を使って、その値を y2 に格納しています。

VariableScope2.java
/*  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*/ }
コンソール
main x = 100
test y = 200

Completed with exit code: 0
変数のスコープのイメージ(2)
変数のスコープのイメージ(2)

さて、呼び出し側とメソッド定義で同じ名前の変数を宣言しても、それらは別の変数と見なされます。

次の例では、メソッド main とメソッド test の両方で、変数 x を宣言しています。 メソッド main x に100を格納し、メソッド test x の値を200に変更しているように見えます。 しかし、 main x の値は100のままです。 メソッド test では、 main x でなく、 test x に200を格納したのです。

VariableScope3.java
/*  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*/ }
コンソール
test x = 200
main x = 100

Completed with exit code: 0
変数のスコープのイメージ(3)
変数のスコープのイメージ(3)

どうしても、呼び出し側とメソッド定義で同じ変数を使いたい場合は、 クラス変数 class variable )というものを使います。 これは、 class の直下で宣言する変数で、

static int 変数名;

などと書きます。 クラス変数は、呼び出し側でもメソッド定義でも同じ変数と見なされます。

次の例では、クラス変数 x を宣言しています。 メソッド main x に100を格納し、メソッド test x の値を200に変更します。 今度は、 main でも test でも、 x の値は200になります。

VariableScope4.java
/*  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*/ }
コンソール
test x = 200
main x = 200

Completed with exit code: 0
変数のスコープのイメージ(4)
変数のスコープのイメージ(4)

ブール値メソッド

これまでに扱ったメソッドは、値を返さないか、整数や実数を返すものでした。 その他のメソッドとして、真理値を返すものが考えられます。 真理値を返すメソッドは、 ブール値メソッド Boolean-valued mothod )と呼ばれます。 ブール値メソッドは、if文の条件式をメソッドにまとめるときなどに使われます。

例えば、生年月日と今日の日付を入力して、今日が誕生日かどうかを判定する問題を考えます。

日付をどのようにデータにするかは、いくつか方法がありますが、ここでは8桁形式を利用します。 つまり、2020年12月1日を整数20201201で表します。 日付の8桁形式には、次のような利点があります。

日付の8桁形式の欠点は、以下のとおりです。

さて、日付の8桁形式を利用して誕生日を判定するには、生年月日の下4桁と今日の日付の下4桁が一致すればよいです。 8桁形式の下4桁は、10000で割った余りで取り出せます。 この条件判定をプログラムで行うと、次のようになります。

Birthday1.java
/*  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*/ }
コンソール
生年月日を8桁形式で入力してください: 20001211
今日の日付を8桁形式で入力してください: 20201211
今日は誕生日です。

Completed with exit code: 0
コンソール
生年月日を8桁形式で入力してください: 20001212
今日の日付を8桁形式で入力してください: 20201211
今日は誕生日ではありません。

Completed with exit code: 0

このプログラムのif文の条件式をメソッドにまとめます。 このメソッドは、条件に合うか合わないかを判定するものなので、真理値を返す、すなわちブール値メソッドになります。 メソッドの名前は isBirthday とします。

メソッド定義では、真理値を返すので、 static boolean と指定します。 そして、条件式の値を return で返します。

プログラムは次の通りです。

Birthday2.java
/*  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*/ }

演習11

生年月日を入力すると、21世紀生まれかどうかを判定するプログラムを作成してください。 条件判定にはブール値メソッドを使うこととします。

メソッドの名前は isBornIn21C とします。 このメソッドの引数は、整数 birth です。 このメソッドは真理値を返すので、 static boolean と指定します。 メソッド定義では、 birth が2001年1月1日以降という条件式の値を return で返します。

BirthAge.java
import java.io.*;

class BirthAge {
    public static void main (String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);


    }


}
コンソール
生年月日を8桁形式で入力してください: 20010101
21世紀生まれです。

Completed with exit code: 0
コンソール
生年月日を8桁形式で入力してください: 20001231
21世紀生まれではありません。

Completed with exit code: 0

余力のある人は、今日の日付も入力するようにし、成人(20才以上)を判定するブール値メソッド isAdult も定義し、これを呼び出して、成人かどうかの判定もしてください。

コンソール
生年月日を8桁形式で入力してください: 20001211
今日の日付を8桁形式で入力してください: 20201211
21世紀生まれではありません。
成人です。

Completed with exit code: 0
コンソール
生年月日を8桁形式で入力してください: 20001212
今日の日付を8桁形式で入力してください: 20201211
21世紀生まれではありません。
成人ではありません。

Completed with exit code: 0

レポート課題

今日の演習11の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(12月11日)を明記してください。


参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2020年12月11日更新
小西 善二郎 <konishi@cis.twcu.ac.jp>
Copyright (C) 2020 Zenjiro Konishi. All rights reserved.