目次 | 索引 |
---|---|
データ型 ( data type ) とは、データの種類のことです。 これまでに、整数、配列、およびクラスの3種類のデータ型を扱ってきました。 Java言語には、この他のデータ型も用意されています。
Java言語のデータ型は、まず基本データ型と参照データ型の2つに大きく分類されます。 基本データ型 ( primitive data type ) には、整数型、浮動小数点数型、論理型、および文字型があります。 参照データ型 ( reference data type ) には、クラス型と配列型があります。 以下は基本データ型の詳細です。
種類 | 型名 | ビット | 説明 |
---|---|---|---|
整数型 | byte |
8 | -27(-128)〜27- 1(127) |
整数型 | short |
16 | -215(-32768)〜215- 1(32767) |
整数型 | int |
32 | -231〜231- 1(9桁程度) |
整数型 | long |
64 | -263〜263- 1(18桁程度) |
浮動小数点数型 | float |
32 | 指数+38〜-45, 有効桁数7桁程度 |
浮動小数点数型 | double |
64 | 指数+308〜-324, 有効桁数14桁程度 |
論理型 | boolean |
- | trueまたはfalse |
文字型 | char |
16 | \u0000(0)〜\uFFFF(65535) |
コンピュータのデータの単位は ビット ( bit ) であることを思い出してください。 ただし、これは理論上の話です。 現実のコンピュータ・システムは、 バイト ( byte ) を単位としています。 1バイトは8ビットです。 基本データ型が8ビット単位であるのは、ここに理由があります。
整数を扱う場合、普通は
int
型を用います。
ただし、
int
型は9桁程度が限界であり、これを超えますと意味のない計算をしてしまいます。
int
型の範囲を超えるような大きい数を扱うときに、
long
型を用います。
浮動小数点数
(
floating point number
)
とは、小数点をずらすことによって、非常に大きな数や非常に小さな数も表現できるようにした小数のことです。
浮動小数点数を扱う場合、普通は
double
型を用います。
限られたビット数で表現する以上、小数点をずらす桁数には限度がありますし、小数の精度にも限界があります。
論理型
(
logical type
)
とは、真理値を表わすデータ型です。
ここで
真理値
(
truth value
)
とは、真を表す記号 true と偽を表す記号 false のことだと思ってください。
Java では、型名
boolean
で論理型を表わします。
値が論理型である式を、
ブール式
(
Boolean expression
)
とよびます。
これまで「条件が成り立つ」、「条件が成り立たない」と言ってきたことは、正確にはブール式の値が true になること、false になることです。
Javaは、文字(
char
型)を1バイトではなく2バイトで表現します。
これは、英数字だけではなく、漢字なども文字として扱おうという設計です。
なお、ちょうど1バイトで表現されるデータ型として、バイト(
byte
)が用意されています。
文字は、内部では整数として処理されます。 この、文字から整数への対応を 文字符号 ( character code ) と呼びます。 Javaの採用している文字符号は、 Unicode と呼ばれる体系です。 Unicodeは ASCII という体系の拡張になっています。 主な文字のASCII符号は次の通りです。
制御文字 | 水平タブ | 改行 | 復帰 | スペース |
---|---|---|---|---|
表示 | '\t' | '\n' | '\r' | ' ' |
符号 | 9 | 10 | 13 | 32 |
文字 | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
符号 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
文字 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
符号 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
文字 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
符号 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
文字 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
符号 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
文字 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
符号 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
文字 | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
符号 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |
プログラムの中で文字を表す場合、その文字をシングルクオート(
'
)で囲みます。
ただし、シングルクオート自身、およびダブルクオート(
"
)、バックスラッシュ(
\
)については、それぞれ
'\''
,
'\"'
,
'\\'
とします。
前回、以下のようなプログラムを紹介しました。
/* 1*/ class Time { /* 2*/ int hour, minute; /* 3*/ }
/* 1*/ class TimeTest5 { /* 2*/ public static void main (String[] args) { /* 3*/ Time x = new Time(); /* 4*/ setHour(x, 14); /* 5*/ setMinute(x, 45); /* 6*/ System.out.println(getHour(x) + ":" + getMinute(x)); /* 7*/ setMinute(x, 30); /* 8*/ System.out.println(getHour(x) + ":" + getMinute(x)); /* 9*/ } /* 10*/ static int getHour (Time t) { /* 11*/ return t.hour; /* 12*/ } /* 13*/ static int getMinute (Time t) { /* 14*/ return t.minute; /* 15*/ } /* 16*/ static void setHour (Time t, int hour) { /* 17*/ t.hour = hour; /* 18*/ } /* 19*/ static void setMinute (Time t, int minute) { /* 20*/ t.minute = minute; /* 21*/ } /* 22*/ }
b04a001@AsiaA1:~/comp2b% java TimeTest5 14:45 14:30 b04a001@AsiaA1:~/comp2b%
ファイルTime.javaではクラスの定義を行い、ファイルTimeTest5.javaでは実行プログラムとメソッドの定義を行っています。 次のようにしますと、クラス定義とメソッド定義を一つにまとめることができます。
/* 1*/ class Time { /* 2*/ int hour, minute; /* 3*/ static int getHour (Time t) { /* 4*/ return t.hour; /* 5*/ } /* 6*/ static int getMinute (Time t) { /* 7*/ return t.minute; /* 8*/ } /* 9*/ static void setHour (Time t, int hour) { /* 10*/ t.hour = hour; /* 11*/ } /* 12*/ static void setMinute (Time t, int minute) { /* 13*/ t.minute = minute; /* 14*/ } /* 15*/ }
/* 1*/ class TimeTest5 { /* 2*/ public static void main (String[] args) { /* 3*/ Time x = new Time(); /* 4*/ Time.setHour(x, 14); /* 5*/ Time.setMinute(x, 45); /* 6*/ System.out.println(Time.getHour(x) + ":" + Time.getMinute(x)); /* 7*/ Time.setMinute(x, 30); /* 8*/ System.out.println(Time.getHour(x) + ":" + Time.getMinute(x)); /* 9*/ } /* 10*/ }
メソッド定義の形は同じですが、メソッド呼出しの形は変わります。 値を返さないメソッドを呼び出すには、文
classname.methodname(argument, ...);
を用います。 ここで classname は、メソッドが定義されているクラスの名前です。 値を返すメソッドを呼び出すには、式
classname.methodname(argument, ...)
を用います。
以前、メソッドにはインスタンスメソッドとクラスメソッドがあると言いました。 これまではクラスメソッドのみを使ってきましたが、Javaらしいプログラムではインスタンスメソッドのほうがよく用いられます。 クラスメソッドと比較しながら、インスタンスメソッドについて説明します。
上記のプログラムを、インスタンスメソッドを用いて書きなおしますと、次のようになります。
/* 1*/ class Time { /* 2*/ int hour, minute; /* 3*/ int getHour () { /* 4*/ return this.hour; /* 5*/ } /* 6*/ int getMinute () { /* 7*/ return this.minute; /* 8*/ } /* 9*/ void setHour (int hour) { /* 10*/ this.hour = hour; /* 11*/ } /* 12*/ void setMinute (int minute) { /* 13*/ this.minute = minute; /* 14*/ } /* 15*/ }
/* 1*/ class TimeTest5 { /* 2*/ public static void main (String[] args) { /* 3*/ Time x = new Time(); /* 4*/ x.setHour(14); /* 5*/ x.setMinute(45); /* 6*/ System.out.println(x.getHour() + ":" + x.getMinute()); /* 7*/ x.setMinute(30); /* 8*/ System.out.println(x.getHour() + ":" + x.getMinute()); /* 9*/ } /* 10*/ }
まず、メソッド定義を実行プログラム(
main
)には並べて書かず、フィールド定義に並べて書きます。
レコード型としてのクラスはフィールドとコンストラクタを定義しますが、一般のクラスはさらにメソッドも定義します。
メソッドは、実行プログラムよりもデータ(インスタンス)に強く結び付くと考えます。
次に、キーワード
static
を取り除きます。
メソッド定義で
static
と書くとクラスメソッド、書かないとインスタンスメソッドになります。
メソッド呼出しの形も変えます。 値を返さないインスタンスメソッドを呼び出すには、文
instance.methodname(argument, ...);
を用います。 ここで instance は、インスタンスを値とする式です。 例えば、インスタンス(への参照)が格納された変数などです。 値を返すインスタンスメソッドを呼び出すには、式
instance.methodname(argument, ...)
を用います。 なお、括弧がなければインスタンスのフィールドにアクセスする形になります。
この式
instance
は、メソッド呼出しの実引数としての役割を果たします。
この実引数に対応する仮引数は、メソッド定義でのキーワード
this
です。
メソッド呼出しの際、
this
にはインスタンス
instance
への参照がコピーされます。
インスタンスメソッドとは、引数の中からインスタンスを一つ選び、それを特別扱いしたものと考えてください。
特別扱いされたインスタンスは、実引数としては、括弧の中ではなく、メソッド名の左に書かれます。
仮引数としては、括弧の中では定義されず、キーワード
this
で表されます。
この、引数の一つのインスタンスを特別扱いすることは、 メッセージ受渡しモデル ( message-passing model ) に基づいています。 これは、データ(インスタンス)がメッセージを受け取ると、それに応じて操作(メソッド)が引き起こされるという考え方です。 Javaでのメッセージは、メソッド名のことだと思ってください。 インスタンスにメッセージを送りますと、そのインスタンスのクラスで定義されたメソッドが起動されるということです。 メッセージ受渡しモデルに従いますと、上記のメソッド呼出しは、インスタンス instance にメッセージ methodname ( argument , ... ) を送ることに相当します。
インスタンスメソッドにできて、クラスメソッドにできないことのひとつに、メソッド定義で
this
を用いることがあげられます。
this
は、インスタンスメソッドの呼出しのときにメッセージを受け取ったインスタンスを指します。
クラスメソッドでは、メッセージを受け取るインスタンスが存在しませんので、
this
が使えないのです。
前回は、以下のようなプログラムで、生まれた年の計算をしました。
/* 1*/ class Person { /* 2*/ int age, year; /* 3*/ Person (int age, int year) { /* 4*/ this.age = age; /* 5*/ this.year = year; /* 6*/ } /* 7*/ }
/* 1*/ class PersonMain { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ Person[] persons = { /* 5*/ new Person(20, 2005), /* 6*/ new Person(15, 2005), /* 7*/ new Person(10, 2005), /* 8*/ new Person(5, 2005), /* 9*/ new Person(0, 2005) /* 10*/ }; /* 11*/ for (i = 0; i < persons.length; i++) { /* 12*/ System.out.print(persons[i].age); /* 13*/ System.out.print(" years old in "); /* 14*/ System.out.print(persons[i].year); /* 15*/ System.out.print(", "); /* 16*/ persons[i].year = persons[i].year - persons[i].age; /* 17*/ persons[i].age = 0; /* 18*/ System.out.print(persons[i].age); /* 19*/ System.out.print(" years old in "); /* 20*/ System.out.print(persons[i].year); /* 21*/ System.out.println(); /* 22*/ } /* 23*/ } /* 24*/ }
b04a001@AsiaA1:~/comp2b% java PersonMain 20 years old in 2005, 0 years old in 1985 15 years old in 2005, 0 years old in 1990 10 years old in 2005, 0 years old in 1995 5 years old in 2005, 0 years old in 2000 0 years old in 2005, 0 years old in 2005 b04a001@AsiaA1:~/comp2b%
これを、インスタンスメソッドを用いて書き直しますと、次のようになります。
ファイルPerson.javaでは、メソッド
toBirthYear
を定義します。
このメソッドは、0才のときのデータに変更するものです。
このメソッドに引数はありません。
このメソッドは値を返しませんので、
void
と指定します。
また、メソッド
printPerson
も定義します。
このメソッドは、西暦何年に何才かを出力するものです。
このメソッドに引数はありません。
このメソッドは値を返しませんので、
void
と指定します。
/* 1*/ class Person { /* 2*/ int age, year; /* 3*/ Person (int age, int year) { /* 4*/ this.age = age; /* 5*/ this.year = year; /* 6*/ } /* 7*/ void toBirthYear () { /* 8*/ this.year = this.year - this.age; /* 9*/ this.age = 0; /* 10*/ } /* 11*/ void printPerson () { /* 12*/ System.out.print(this.age); /* 13*/ System.out.print(" years old in "); /* 14*/ System.out.print(this.year); /* 15*/ } /* 16*/ }
ファイルPersonMain.javaでは、インスタンスメソッド toBirthYear と printPerson を呼び出します。 14行目は、 i 番目の人を表すインスタンス persons [ i ] に、0才のときのデータに変更するようにとメッセージ toBirthYear () を送るという意味です。 また、12行目と15行目は、インスタンス persons [ i ] に、西暦何年に何才かを出力するようにとメッセージ printPerson () を送るという意味です。
/* 1*/ class PersonMain { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ Person[] persons = { /* 5*/ new Person(20, 2005), /* 6*/ new Person(15, 2005), /* 7*/ new Person(10, 2005), /* 8*/ new Person(5, 2005), /* 9*/ new Person(0, 2005) /* 10*/ }; /* 11*/ for (i = 0; i < persons.length; i++) { /* 12*/ persons[i].printPerson(); /* 13*/ System.out.print(", "); /* 14*/ persons[i].toBirthYear(); /* 15*/ persons[i].printPerson(); /* 16*/ System.out.println(); /* 17*/ } /* 18*/ } /* 19*/ }
ある鉄道会社で、旅行のキャンペーンを行っているとします。 そのキャンペーンとは、乗車券と特急券の合計が5千円以上ならば、乗車券を1割引するというものです。 これまでに、次の5人の旅行客が乗車券と特急券を購入したとします。 割引前の乗車券と特急券を格納した後、それらを割り引くという計算をしてください。
割引前 | 割引後 | ||||
---|---|---|---|---|---|
乗車券 | 特急券 | 合計 | 乗車券 | 特急券 | 合計 |
2000 | 1000 | 3000 | 2000 | 1000 | 3000 |
3000 | 1000 | 4000 | 3000 | 1000 | 4000 |
3000 | 2000 | 5000 | 2700 | 2000 | 4700 |
4000 | 2000 | 6000 | 3600 | 2000 | 5600 |
4000 | 3000 | 7000 | 3600 | 3000 | 6600 |
ファイルTrip.javaでは、乗車券と特急券を格納するために、クラス
Trip
を定義します。
フィールド
ticket
には乗車券を、
express
には特急券を格納します。
コンストラクタは、引数が
ticket
,
express
の順になるように定義します。
ファイルTrip.javaでは、インスタンスメソッド
discount
を定義します。
これは、乗車券と特急券の合計が5千円以上ならば、乗車券を1割引するものです。
このメソッドに引数はありません。
このメソッドは値を返しませんので、
void
と指定します。
メソッド定義の要点は、1割引の計算は、9倍して10で割ることです。
ファイルTrip.javaでは、インスタンスメソッド
printTrip
を定義します。
これは、「乗車券+特急券=合計」を出力するものです。
このメソッドに引数はありません。
このメソッドは値を返しませんので、
void
と指定します。
メソッド定義の要点は、合計の部分は式の値を出力することです。
ファイルTripMain.javaでは、次のようにコンストラクタを呼び出して、配列 trips にすべての旅行客の乗車券と特急券を格納します。
Trip[] trips = { new Trip(2000, 1000), new Trip(3000, 1000), new Trip(3000, 2000), new Trip(4000, 2000), new Trip(4000, 3000) };
一人一人の旅行客に対して、メッセージ printTrip () を送って割引前を画面に出力し、メッセージ discount () を送って割引をし、メッセージ printTrip () を送って割引後を画面に出力するというアルゴリズムに従って、プログラムを作成してください。
b04a001@AsiaA1:~/comp2b% java TripMain 2000+1000=3000 -> 2000+1000=3000 3000+1000=4000 -> 3000+1000=4000 3000+2000=5000 -> 2700+2000=4700 4000+2000=6000 -> 3600+2000=5600 4000+3000=7000 -> 3600+3000=6600 b04a001@AsiaA1:~/comp2b%
余力のある人は、これとは別に、クラスメソッドを用いたプログラムを作成してください。 ファイルTrip2.javaでは、フィールド、コンストラクタ、クラスメソッドを定義し、ファイルTripMain2.javaでそれらを呼び出すものとします。
今日の演習10の答案(Javaプログラム)をメールで提出してください。 メールの送信には学内のコンピュータ(メール・サーバ)を用い、送信先はkonishi@twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(6月24日)を明記してください。