今日から、ついに「オブジェクト指向」について学習する。
ここで、挫折する人が多いようです。
(わたしは「メソッド」で数回、挫折したので、なんとも言えないですが……)
■オブジェクト指向って??■
「オブジェクト指向」と初めて聞いたとしたら、「それは、なに?」と思うはずです。
わからないことを、すぐに検索して調べる人は、まずwikipediaを見るでしょう。
http://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91
「オブジェクト同士の相互作用として、システムの振る舞いをとらえる考え方。」
と書いてある。
「オブジェクト指向プログラミング」も見てみる。
http://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0
「相互にメッセージを送りあう、オブジェクトの集まりとしてプログラムを構成する技法」
これで理解出来るなら問題はないですね。
わたしは、出来ませんでした。
「オブジェクト同士の相互作用として、システムの振る舞いをとらえる考え方。」
wikipedia に書いてあるように、オブジェクト指向とは、考え方。
これ!!という完璧な定義はない。
登場人物の気持ちを考えなさい、という国語の問題に似ていますね。
正解は、おそらく作者しか決められないけれど、大まかな正解が存在していて
限りなく正解に近づくための勉強方法がある。
視点を変えて、「オブジェクト指向」じゃなくて困ることって??と考えてみる。
昔は、計算機の性能が現代とは比べ物にならないくらい低かった。
そのため、大規模なソフトウェア開発は行われていなかった。
今まで学習してきた、手続き型(逐一、指示を出して上から順に実行)で問題がなかった。
年々、計算機の性能が上がっていき、大規模なソフトウェア開発が必要になった。
そうなると、ソースコードの量が膨大になり、どんどん複雑化して
人間が把握出来なくなった。(あくまでも、人間が!!)
人間が、自分たちで書いたコードに対処しきれなくなってしまったわけです。
(さきほどの、wikipediaの「オブジェクト指向プログラミング」のページに背景が書いてあるので、読んでみるといいかもしれない。)
人間が対処するために生まれたのが 「オブジェクト指向プログラミング」 なのです。
(コンピュータは適切な指示さえ与えれば、どんなに汚いコードでも困ったりせずに、こなしてくれますよね)
これだけだと、よくわからないですね。
どうやって対処するの??結局、どうなるの?メリットは??
疑問が尽きない。
少しずつ、さらっと説明。
■オブジェクト指向 メリット■
・柔軟性があがる
・再利用性があがる
・保守性がよくなる
以上の三つが一般的によく言われているメリット。
ただ、この時点では、メリットを享受していない。
なにも書いていないし、概要を学んでいるだけだから。
最低限、理解しなくてはいけないことは、
人間が、コードを把握して、対処出来る!!(逆に、出来なくては意味がない)
ということ。
メリットは、わかったけれど、具体的にどうしたらメリットを受けられるかというと。
三大要素というものが存在する。
■オブジェクト指向 三大要素■
・カプセル化
・継承
・ポリモーフィズム
ここは、今後、学習していくから、こういう3つの要素があるんだな、とさらっと流す。
■オブジェクトって??■
ここまで、何度も出てきた「オブジェクト」ってなんだろう??
オブジェクトは、「属性」と「操作」をもったもの。
具体的にどういうことか、
下の絵を参考にして、オブジェクトを作ってみる。
まず、この絵が何を表現しているかというと
「うちの近所の争い」(の一部)です。
野良猫がいて、餌やりのおばさんがいて、隣のおばちゃんがいて……。
野良猫は、餌をねだります。
餌やりおばさんは、野良猫に餌をあげます。
それを、ときどき、隣のおばちゃんが怒ります。
怒られた餌やりおばさんと猫は逃げていきます。
それを、わたしは見ています。
3個のオブジェクトが作られました。
「野良猫」、「餌やりおばちゃん」、「隣のおばちゃん」。
属性は、「種族」のみ。これが、全員、知っている登場人物だったら「名前」、「年齢」があったかもしれない。
操作は、行動。他にも様々な行動をするけど、少しだけ書きました。
(実際には、隣のおばちゃんは「世間話をする」などがあります)
絵には、「自分」が登場しているのに、オブジェクトは作られていませんね。
ここでは「自分」は「近所の争い」の観測者であり、創造主、神様です!!
わたしが、現実世界を見て、設計しています。
(オブジェクト指向は設計がとっても大事です。)
野良猫と餌やりおばちゃんの操作である「逃げる」、は
隣のおばちゃんの「怒る」があって発生する。
野良猫が「餌をねだって」、餌やりおばさんが「餌をあげて」、野良猫が「食べる」。
このように、オブジェクトが互いに操作を呼び出しあっている。
また、餌やりおばちゃんは野良猫に「属性-名前 : タマちゃん」をつけているかもしれない。
野良猫は、餌やりおばちゃんを「属性 - タイプ : 善」、隣のおばちゃんを「属性 - タイプ : 悪」としているかもしれない。
オブジェクトは、互いに属性を読み書き出来る。
そして、互いに呼び出しあったり、読み書きして、1つのプログラムとなる。
今日はここまで。
おおまかな概念を理解したから、次回は、具体的に学んでいく。
2014年9月30日火曜日
2014年9月26日金曜日
- メソッド - Java
今日は「メソッド」について学習する。
ここが、初学者にとっては、最初の難関になる。
(わたしは、ここで、数回、挫折した。)
しかし、今までずっと「メソッド」は使ってきている。
- 基本構造 - で説明したように
メソッドの中に変数や、命令、分岐などを書いてきた。
今まで書いてきたものは、全て、「main メソッド」の中。
今日は、「main メソッド」以外のメソッドを作っていく。
「メソッド」は、複数の文をまとめて名前をつけたもの。
mainメソッドは、どの順番で書いても、必ず初めに実行される。
メソッドはmainメソッド以外からでも呼び出せる。
各メソッドは、機能ごとにわけるといい。
mainメソッドに全て書くことも出来るけど、メソッドに細かく分けることによっていくつかメリットがある。
・mainメソッドで、分割したメソッドを呼び出して使用すると、コードがスッキリする。
・機能単位でメソッドを分割すると、全体の把握が容易になり、修正もしやすくなる。
・メソッドを繰り返し使用できるから、同じ処理を書く手間が省ける。
メソッドの使い方は、以下のとおり。
定義して、呼び出す。
これが、基本だから、あとは細かい作法を理解するだけ。
■引数■
おそらく、ここから、難しくなってくる。
メソッドの定義、呼び出しの方法に書かれている、「引数」とは、なにか。
メソッドを呼び出す際に呼び出し元から渡される値のことを引数という。
文章だけだと、よくわからないかもしれない。
この場合、呼び出すのは mainメソッド
受け取るのは Englishメソッド、Japaneseメソッド、Germanyメソッド。
呼び出し元(mainメソッド)から渡される値(引数)は
String型(文字列)の "Hello"、"こんにちは"、"Guten tag"
一番はじめに書いた MethodConceptクラスでは
引数を渡していないため
public static void main(String[] args) {
name ( );
age ( );
}
public static void name() {
:
}
public static void age() {
:
}
のように、メソッド名の後の ( ) に、何も入っていない。
上の図のように、値は、0個~複数個、渡すことができる。
■戻り値■
これが、今日の山場。
これさえ理解できれば、じゅうぶん。
(わたしは、以前、理解することを諦めて、別のものを作り始めたら、理解できていました)
呼び出されたメソッドから、呼び出し元のメソッドに値を返すことを「値を戻す」という。
また、その値ことを、「戻り値」という。
return 戻り値 ;
というのは、return文という。
return の横の 戻り値 が呼び出し元に戻せる値。
メソッドを終了させる役割もある。
また、一行目の 戻り値の型 というのは
return によって、戻される値と同じ型を指定する必要がある。
たとえば、
return 100; だと int
return "AIUEO" だと String
■オーバーロード■
メソッドに同じ名前をつけることは基本的に出来ない。
例外的に、同じ名前のメソッドを定義することはできる。
それを、オーバーロードという。
方法は2つある。
・仮引数(受け取る変数のこと)の型が異なる場合
・仮引数の数が異なる場合
まずは、仮引数の型が異なる場合
次に、仮引数の数が異なる場合
■引数、戻り値に配列を使う■
メソッドの引数には、変数型だけでなく、配列型を使える。
素数を出すプログラムは、今までの知識だけで作れるのですが、今回は、手打ちで!!
そのうち、書きます。
今まで、 int ~ としていたところを、
int [ ] ~ に変えると配列を渡せる。
ただ、配列を渡すときは、変数を渡すときとは、少し違う。
メソッドを呼び出すときに渡される変数は、変数そのものではなく、値である。
値そのものが渡されることを、値渡しという。
配列の場合は、値そのものではなく、要素のアドレスが渡される。
このように、引数に値ではなく、アドレスを渡すことを、参照渡しという。
このアドレス部分に関しては、別の機会に書きたい。
具体的にどういうことかというと。
値を返していないのに、呼び出し元(mainメソッド)の配列の中身がかきかわっている。
なので、mainメソッドと、testArrayメソッドで、参照している配列は
全く同じものだということになる。
(変数を引数として受け取る場合だと、それぞれのメソッドで宣言している変数は同じ名前であっても別のもの。)
これは、戻り値に配列を用いる場合でも同様。
ここが、初学者にとっては、最初の難関になる。
(わたしは、ここで、数回、挫折した。)
しかし、今までずっと「メソッド」は使ってきている。
- 基本構造 - で説明したように
メソッドの中に変数や、命令、分岐などを書いてきた。
今まで書いてきたものは、全て、「main メソッド」の中。
今日は、「main メソッド」以外のメソッドを作っていく。
「メソッド」は、複数の文をまとめて名前をつけたもの。
mainメソッドは、どの順番で書いても、必ず初めに実行される。
メソッドはmainメソッド以外からでも呼び出せる。
各メソッドは、機能ごとにわけるといい。
mainメソッドに全て書くことも出来るけど、メソッドに細かく分けることによっていくつかメリットがある。
・mainメソッドで、分割したメソッドを呼び出して使用すると、コードがスッキリする。
・機能単位でメソッドを分割すると、全体の把握が容易になり、修正もしやすくなる。
・メソッドを繰り返し使用できるから、同じ処理を書く手間が省ける。
メソッドの使い方は、以下のとおり。
定義して、呼び出す。
これが、基本だから、あとは細かい作法を理解するだけ。
package blog; public class MethodConcept { // mainメソッドから、2つのメソッドを呼び出します public static void main(String[] args) { System.out.println("ここはメインメソッドです"); System.out.println("メソッドを呼び出してみます"); name(); age(); } public static void name() { String myName = "ともみ!!"; System.out.println("ここは nameメソッドです"); System.out.println("わたしの名前は" + myName + "です"); } public static void age() { int myAge = 27; System.out.println("ここは ageメソッドです"); System.out.println("年齢は" + myAge + "ですよー"); } }
■引数■
おそらく、ここから、難しくなってくる。
メソッドの定義、呼び出しの方法に書かれている、「引数」とは、なにか。
メソッドを呼び出す際に呼び出し元から渡される値のことを引数という。
文章だけだと、よくわからないかもしれない。
package blog; public class Argument { // メインメソッドから、引数を1つだけ渡して実行するプログラム public static void main(String[] args) { System.out.println("メソッドを呼び出します"); // Englishメソッドに "Hello" を渡して呼び出す English("Hello"); // Japaneseメソッドに "こんにちは" を渡して呼び出す Japanese("こんにちは"); // Germanyメソッドに "Guten tag" を渡して呼び出す Germany("Guten tag"); System.out.println("呼び出し完了!!!"); } // Englishメソッドを定義する // String型の文字列を1つ受け取る /* * 文字列変数 greetings の有効範囲はブロック内だけだから * 別のメソッドで使われている greetings は別のもの */ public static void English(String greetings) { System.out.println("英語での挨拶「" + greetings + "」"); } // Japaneseメソッドを定義する // String型の文字列を1つ受け取る public static void Japanese(String greetings) { System.out.println("日本語での挨拶「" + greetings + "」"); } // Germanyメソッドを定義する // String型の文字列を1つ受け取る public static void Germany(String greetings) { System.out.println("ドイツ語での挨拶「" + greetings + "」"); } }
この場合、呼び出すのは mainメソッド
受け取るのは Englishメソッド、Japaneseメソッド、Germanyメソッド。
呼び出し元(mainメソッド)から渡される値(引数)は
String型(文字列)の "Hello"、"こんにちは"、"Guten tag"
一番はじめに書いた MethodConceptクラスでは
引数を渡していないため
public static void main(String[] args) {
name ( );
age ( );
}
public static void name() {
:
}
public static void age() {
:
}
のように、メソッド名の後の ( ) に、何も入っていない。
上の図のように、値は、0個~複数個、渡すことができる。
package blog; public class MultipleArgument { // mainメソッドから、2つのメソッドに引数を渡して呼び出す public static void main(String[] args) { System.out.println("ファミコンで遊びます"); System.out.println("モンスターを呼び出します"); // slimeメソッドに、引数を2つ渡して呼び出す slime("スライム", 3); // dragonKingメソッドに、引数を3つ渡して呼び出す dragonKing("りゅうおう", 130, 140); System.out.println("モンスターをすべて呼び出しました"); } // slimeメソッドを定義する // String型も文字列、int型の整数の2つを受け取る public static void slime(String name, int hp) { System.out.println(name + "が現れた!!!"); System.out.println("体力は" + hp + "だ"); } // dragonKingメソッドを定義する // String型の文字列、int型の整数を2つ、計3つを受け取る public static void dragonKing(String name, int hp, int atack) { System.out.println(name + "が現れた!!!"); System.out.println("体力は" + hp + "だ!!"); System.out.println("攻撃力" + atack + "だ!!"); } }
■戻り値■
これが、今日の山場。
これさえ理解できれば、じゅうぶん。
(わたしは、以前、理解することを諦めて、別のものを作り始めたら、理解できていました)
呼び出されたメソッドから、呼び出し元のメソッドに値を返すことを「値を戻す」という。
また、その値ことを、「戻り値」という。
return 戻り値 ;
というのは、return文という。
return の横の 戻り値 が呼び出し元に戻せる値。
メソッドを終了させる役割もある。
また、一行目の 戻り値の型 というのは
return によって、戻される値と同じ型を指定する必要がある。
たとえば、
return 100; だと int
return "AIUEO" だと String
package blog; public class ReturnValue { // lifeメソッドから、mainメソッドへ値を返して、何日生きてきたかを調べる public static void main(String[] args) { System.out.println("lifeメソッドを呼び出します!!"); // lifeメソッドに int型の整数 27 , 365 を渡す // lifeday (中身は age * day) が返ってきて、allLife に代入される int allLife = life(27, 365); System.out.println("わたしは、おおまかに" + allLife + "日、生きてますよー"); } // lifeメソッドを定義する。int型の整数を2つ受け取る public static int life(int age, int day) { // lifeメソッドが呼び出されると受け取った引数が代入される int lifeDay = age * day; // lifeメソッドが呼び出されると、 lifeday (戻り値)が返される。 return lifeDay; } }
■オーバーロード■
メソッドに同じ名前をつけることは基本的に出来ない。
例外的に、同じ名前のメソッドを定義することはできる。
それを、オーバーロードという。
方法は2つある。
・仮引数(受け取る変数のこと)の型が異なる場合
・仮引数の数が異なる場合
まずは、仮引数の型が異なる場合
package blog; public class DifferentModel { // 同じ名前のメソッドを定義して、呼び出すプログラム public static void main(String[] args) { System.out.print("今週の"); // 仮引数が String型,String型 の studyメソッドに文字列を渡す study("英語", "数学"); // 仮引数が int型、int型 の studyメソッドに整数を渡す // allTime に time * day を戻り値として受け取る int allTime = study(6, 5); System.out.println(allTime + "時間です"); } // String型 の studyメソッドを定義する public static String study(String subject1, String subject2) { System.out.println(subject1 + "と" + subject2 + "の勉強時間は"); // 値を返さないので、 null を返す // ※値を返さないので、 本当は、void型のメソッドにしたほうがいい※ return null; } // int型の studyメソッドを定義する public static int study(int time, int day) { // int型の studyメソッドが呼び出されると int型の整数を2つ受け取る // 整数を受け取った time*day が allTime に代入される int allTime = time * day; // return で allTime を呼び出し元に渡す return allTime; } }
次に、仮引数の数が異なる場合
package blog; public class DifferentNumber { // オーバーロードを使い、正方形、長方形、三角形の面積を求めるプログラム public static void main(String[] args) { int x = 4; int y = 8; int z = 2; // 1つの仮引数をもつdiagramメソッドに int型変数 x を渡し、area を受け取る // 受け取った値を squareArea に代入する int squareArea = diagram(x); System.out.println(squareArea); // 2つの仮引数をもつdiagramメソッドに int型変数 x ,yを渡し、area を受け取る // 受け取った値を rectangleArea に代入する int rectangleArea = diagram(x, y); System.out.println(rectangleArea); // 3つの仮引数をもつdiagramメソッドに int型変数 x ,y,zを渡し、area を受け取る // 受け取った値を triangleArea に代入する int triangleArea = diagram(x, y, z); System.out.println(triangleArea); } // int型のdiagramメソッドを定義し、xを受け取る public static int diagram(int x) { System.out.println("正方形の面積を求める"); System.out.print("一片の長さが" + x + "cmの正方形の面積は"); int area = x * x; // area を返す return area; } // int型のdiagramメソッドを定義し、x,yを受け取る public static int diagram(int x, int y) { System.out.println("長方形の面積を求める"); System.out.print("縦が" + x + "cm,横が" + y + "cmの長方形の面積は"); int area = x * y; // area を返す return area; } // int型のdiagramメソッドを定義し、x,y,zを受け取る public static int diagram(int x, int y, int z) { System.out.println("三角形の面積を求める"); System.out.print("底辺" + x + "cm,高さ" + y + "cmの三角形の面積は"); int area = x * y / z; // area を返す return area; } }
■引数、戻り値に配列を使う■
メソッドの引数には、変数型だけでなく、配列型を使える。
package blog; public class ArgumentArray { // 引数に配列を使って、整数を渡して出力するプログラム public static void main(String[] args) { System.out.println("素数をいくつか、あげてみます"); // int型配列に、整数を代入する int[] array = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }; // primeNumberメソッドに、配列を渡して呼び出す primeNumber(array); } // int型配列を引数として受け取る primeNumberメソッドを定義する public static void primeNumber(int[] array) { // 何個目かを表す int型の整数を宣言して 1 を代入 int turn = 1; // forループを使って、配列をまわす for (int number : array) { System.out.println((turn++) + "個目の素数は" + number); } } }
素数を出すプログラムは、今までの知識だけで作れるのですが、今回は、手打ちで!!
そのうち、書きます。
今まで、 int ~ としていたところを、
int [ ] ~ に変えると配列を渡せる。
ただ、配列を渡すときは、変数を渡すときとは、少し違う。
メソッドを呼び出すときに渡される変数は、変数そのものではなく、値である。
値そのものが渡されることを、値渡しという。
配列の場合は、値そのものではなく、要素のアドレスが渡される。
このように、引数に値ではなく、アドレスを渡すことを、参照渡しという。
このアドレス部分に関しては、別の機会に書きたい。
具体的にどういうことかというと。
package blog; public class CallByReference { // 参照渡しの例 public static void main(String[] args) { // int型配列 に 値を三つ代入する int array[] = { 10, 100, 1000 }; // 配列をまわす for (int i : array) { System.out.println("mainメソッドでは" + i); } // testArrayメソッドに配列を渡す testArray(array); // 配列をまわす for (int i : array) { System.out.println("mainメソッドでは" + i); } } // int型配列を引数として受け取る testArrayメソッドを定義する // void型のメソッドなので、値を返さない(return文無し) public static void testArray(int[] array) { System.out.println("~【始】testArray【始】~"); // for文で配列をまわす for (int i = 0; i < array.length; i++) { array[i]++; // 配列を表示 System.out.println("testArrayメソッドでは" + array[i]); } // 値を返さずに終了 System.out.println("~【終】testArray【終】~"); } }
値を返していないのに、呼び出し元(mainメソッド)の配列の中身がかきかわっている。
なので、mainメソッドと、testArrayメソッドで、参照している配列は
全く同じものだということになる。
(変数を引数として受け取る場合だと、それぞれのメソッドで宣言している変数は同じ名前であっても別のもの。)
これは、戻り値に配列を用いる場合でも同様。
package blog; public class ReturnValueArgs { // 戻り値に配列を使う public static void main(String[] args) { System.out.println("一週間は!"); // dayメソッドに 7 を渡して、 // 受け取った値(アドレス)を int型配列 day に格納 int[] day = day(7); // 拡張for文を使って、配列をまわす for (int i : day) { System.out.println(i + "日!!!"); } } // int型配列を返す dayメソッドを定義する // int week では引数を受け取る public static int[] day(int week) { // 7 を受け取った week を int型配列 newDay に代入する int[] newDay = new int[week]; // for文で配列をまわす for (int i = 0; i < newDay.length; i++) { // 0から始まるため、 1 を足して、newDay[i] に代入 newDay[i] = i + 1; } // 呼び出し元に newDay を返す return newDay; } }
2014年9月25日木曜日
- 配列 - Java
今日は、 配列 について学習する。
配列とは、同一種類の複数データを並び順で格納するデータ構造。
データ構造とは、データの集まりをコンピュータの中で、効果的に扱うため、一定の形式に系統立てて格納するときの形式。
左の図のように
配列は、いくつかあるデータ構造の中の一つである。
業務では、あまり使われない。
同一種類の複数データを並び順で格納する、とは、どういうものなのかみていきたい。
配列のイメージ図は以下のとおり。
要素(element)と呼ばれる箱が、連続して並んでいるのが配列。
この要素とは、格納されているデータ一つ一つのこと。
これだけでは、よくわからないので、実際に書いてみる。
変数と同じように、最初に宣言をする。
次も変数のときと同じように、代入する。
~注意点~
・配列の各要素には、同一種のデータしか格納できない
・添え字は必ず 0 から始まる。
また、「配列変数の宣言」と「要素の作成と代入」は同時におこなうことができる。
double [ ] weight;
weight = new double[5];
を
double [ ] weight = new double [5] ;
という一行にできる。
また、これと同じ内容のコードを、データ構造を使わずに書いた場合。
データ構造を使うと、とてもすっきりしたコードになる。
配列には、省略記法が二種類あり、初期値の代入を、簡単に書くことができる。
実際に使ってみる。
■配列の要素数の取得■
また、配列は要素数を取得(要素の長さを出す)出来る。
書き方は、簡単で
配列変数名のあとに length(長さという意味)をつけるだけ。
■要素数の取得の応用■
for文 の終了条件に、 配列変数名 .length と書くと、
配列の各要素を順番に取り出せる。
この、各要素のはじめから最後まで、順番に取り出すことを、配列を回す、という。
■拡張for文■
さらに応用。
拡張for文とは、
配列の要素を一つずつ取り出すループを簡単に書くために導入された新しいfor文。
データ構造(主に List)で多用されるため、よく理解しておいたほうがいい。
~注意~
バージョンが Java5以降 でしか利用できない!!
int month = 1;
(month++)
のあたりが、美しくないですね。
拡張for文を使うと、以前の普通のfor文で配列を回しているときと比べて、非常にスタイリッシュになる。
新しい構文は、スタイリッシュなようです。
非常に大切だから、拡張for文を使って、いろいろ書いてみるといいかもしれない。
■多次元の配列■
今まで学んだのは、1次元配列。
次は、縦の並びを加えた、2次元配列について学習する。
イメージは以下。
2次元配列の宣言
要素の型 [ ] [ ] 配列変数名 = new 要素の型[ 行数 ][ 列数 ]
2次元配列の要素の利用
配列変数名 [ 行の添え字 ][ 列の添え字 ]
これまでと同じように、一行にまとめて書くことができる
要素の型 [ ] [ ] 配列変数名 = { { 初期値1,初期値2,初期値3...} , { 初期値1,初期値2,初期値3... } } ;
コードがぐちゃぐちゃになってきました。
もう少し、綺麗に書けそうですね。
次は「メソッド」について学習するので、少しは改善されるかもしれません!
配列とは、同一種類の複数データを並び順で格納するデータ構造。
データ構造とは、データの集まりをコンピュータの中で、効果的に扱うため、一定の形式に系統立てて格納するときの形式。
左の図のように
配列は、いくつかあるデータ構造の中の一つである。
業務では、あまり使われない。
同一種類の複数データを並び順で格納する、とは、どういうものなのかみていきたい。
配列のイメージ図は以下のとおり。
要素(element)と呼ばれる箱が、連続して並んでいるのが配列。
この要素とは、格納されているデータ一つ一つのこと。
これだけでは、よくわからないので、実際に書いてみる。
変数と同じように、最初に宣言をする。
次も変数のときと同じように、代入する。
~注意点~
・配列の各要素には、同一種のデータしか格納できない
・添え字は必ず 0 から始まる。
また、「配列変数の宣言」と「要素の作成と代入」は同時におこなうことができる。
double [ ] weight;
weight = new double[5];
を
double [ ] weight = new double [5] ;
という一行にできる。
package blog; public class Array { public static void main(String[] args) { // double型の要素に weight という配列変数名をつける double[] weight; // weight に 5つの要素を作る weight = new double[5]; // 作成した5つの要素に、値を代入する weight[0] = 47.2; weight[1] = 46.2; weight[2] = 46.8; weight[3] = 46.9; weight[4] = 46.7; // weight[4](5番目) を参照する System.out.println("今日の体重は" + weight[4] + "kgだった"); } }
また、これと同じ内容のコードを、データ構造を使わずに書いた場合。
package blog; public class Weight { public static void main(String[] args) { // 変数宣言と代入 double weight1 = 47.2; double weight2 = 46.2; double weight3 = 46.8; double weight4 = 46.9; double weight5 = 46.7; // 変数 weight5 を参照する System.out.println("今日の体重は" + weight5 + "kgだった"); } }
データ構造を使うと、とてもすっきりしたコードになる。
配列には、省略記法が二種類あり、初期値の代入を、簡単に書くことができる。
実際に使ってみる。
package blog; public class Abbreviation { public static void main(String[] args) { // 「配列変数の宣言」と「要素の作成と代入」を同時に行う int[] sleepTime = new int[4]; sleepTime[0] = 420; sleepTime[1] = 460; sleepTime[2] = 480; sleepTime[3] = 380; System.out.println("今日の睡眠時間は" + sleepTime[3] + "分でした"); // 省略した書き方(配列の作成と初期値の代入を同時に行う) int[] studyTime = new int[] { 300, 320, 250, 200 }; System.out.println("今日の勉強時間は" + studyTime[3] + "分でした"); // 省略した書き方(配列の作成と初期値の代入を同時に行う) int[] sports = { 60, 120, 90, 30 }; System.out.println("今日の運動時間は" + sports[3] + "分でした"); } }
■配列の要素数の取得■
また、配列は要素数を取得(要素の長さを出す)出来る。
書き方は、簡単で
配列変数名のあとに length(長さという意味)をつけるだけ。
package blog; public class Acquire { public static void main(String[] args) { // 配列変数の宣言と、要素の作成と代入をおこなう int[] consumptionTime = { 350, 300, 200, 350, 500 }; // consumptionTime.length で、要素の数を取得する System.out.println(consumptionTime.length + "日間、勉強しました"); } }
■要素数の取得の応用■
for文 の終了条件に、 配列変数名 .length と書くと、
配列の各要素を順番に取り出せる。
この、各要素のはじめから最後まで、順番に取り出すことを、配列を回す、という。
package blog; public class TurnArray { // 2014年の祝日を、forループ をつかって、出力するプログラム public static void main(String[] args) { // 配列変数 nationalHoliday に 要素を作成し、値を代入 int[] nationalHoliday = { 2, 1, 1, 1, 4, 0, 1, 0, 2, 1, 3, 1 }; System.out.println("これが、2014年の祝日!!!!"); System.out.println("振り替え休日も込み。"); // 終了条件に nationalHoliday を用いて、配列をまわす。 for (int i = 0; i < nationalHoliday.length; i++) { // 添え字に 変数i を用いて、要素を取得 System.out.println((i + 1) + "月の祝日は" + nationalHoliday[i] + "日間です"); } } }
■拡張for文■
さらに応用。
拡張for文とは、
配列の要素を一つずつ取り出すループを簡単に書くために導入された新しいfor文。
データ構造(主に List)で多用されるため、よく理解しておいたほうがいい。
~注意~
バージョンが Java5以降 でしか利用できない!!
package blog; public class Expansion { // 2014年の祝日を、拡張for文 をつかって、出力するプログラム public static void main(String[] args) { // 配列変数 nationalHoliday に 要素を作成し、値を代入 int[] nationalHoliday = { 2, 1, 1, 1, 4, 0, 1, 0, 2, 1, 3, 1 }; System.out.println("これが、2014年の祝日!!!!第二段!!!"); System.out.println("また振り替え休日も含みます。"); // 変数 month は、何月かを表す変数 // 月は、1月から始まるので、month には 1 を代入 int month = 1; // 拡張for文 for (int holiday : nationalHoliday) { // 任意の変数 holiday のみで、値が代入された要素を呼び出せる System.out.println((month++) + "月の祝日は" + holiday + "日です"); } } }
int month = 1;
(month++)
のあたりが、美しくないですね。
拡張for文を使うと、以前の普通のfor文で配列を回しているときと比べて、非常にスタイリッシュになる。
新しい構文は、スタイリッシュなようです。
非常に大切だから、拡張for文を使って、いろいろ書いてみるといいかもしれない。
■多次元の配列■
今まで学んだのは、1次元配列。
次は、縦の並びを加えた、2次元配列について学習する。
イメージは以下。
2次元配列の宣言
要素の型 [ ] [ ] 配列変数名 = new 要素の型[ 行数 ][ 列数 ]
2次元配列の要素の利用
配列変数名 [ 行の添え字 ][ 列の添え字 ]
これまでと同じように、一行にまとめて書くことができる
要素の型 [ ] [ ] 配列変数名 = { { 初期値1,初期値2,初期値3...} , { 初期値1,初期値2,初期値3... } } ;
package blog; public class TwoDimensions { // 数学と英語の合計勉強時間を出すプログラム public static void main(String[] args) { // 2次元配列の宣言と代入 int[][] time = { { 30, 70, 50 }, { 60, 40, 70, 30, 40 } }; // int型の変数 totalEnglish の宣言 int totalEnglish = 0; // int型の変数 totalMath の宣言 int totalMath = 0; // 拡張for文を使って、一行目の要素を順番に取得 for (int english : time[0]) { // totalEnglish に english を足していく totalEnglish += english; } // time[0](2次元配列の一行目)の要素数を取得 System.out.print(time[0].length + "日間の英語の合計勉強時間は"); System.out.println(totalEnglish + "時間"); // 拡張for文を使って、二行目の要素を順番に取得 for (int math : time[1]) { // totalMath に math を足していく totalMath += math; } // time[1](2次元配列の二行目)の要素数を取得 System.out.print(time[1].length + "日間の数学の合計勉強時間は"); System.out.println(totalMath + "時間"); } }
コードがぐちゃぐちゃになってきました。
もう少し、綺麗に書けそうですね。
次は「メソッド」について学習するので、少しは改善されるかもしれません!
2014年9月21日日曜日
- 繰り返し構文 - Java
繰り返し構文にも、いくつかのバリエーションがある。
今回は、そのバリエーションについて学ぶ。
■while文■
while文 は2種類ある。
前々回、学習した、「while 文」の他に
「do - while文」というもの。
while文は、条件式を評価してから、ブロックを実行する。
判定結果が false の場合、一度もブロックが実行されない。
一つ目の実行結果は、
price の値を 1980 円にしています。
二つ目は、money が足りていないので、何も実行されない。
do-while文は、ブロックを実行してから、条件式を評価する。
判定結果にかかわらず、最低一回は、ブロックを実行する。
必ず、一度は実行されるので、実行結果2のように、
所持金が足りなくても、買い物をしてしまうので注意!!
do-while文は、それほど使わないので、あまり気にしなくてもいい。
■for文■
for文は、繰り返しの回数を指定するときに使う。
1,初期化処理
最初に一回だけ実行される文。
ここで使う変数をループ変数という。
変数名は、なんでもいいけど、通常は i など一文字にする。
すでに使用している変数名は使えない。(ブロック内では使える)
2,繰り返し条件
ブロックの内容を実行する前に評価され、このループを継続するか否かを判断する条件式
3,繰り返し時の処理
for文のブロックを最後まで処理した直後に、自動的に実行される文。
これは、非常に簡単な繰り返し文。
もう少し、複雑なコードを書ける。
■ネスト■
制御構造(条件分岐、繰り返し)は、その中に、別の制御構造を含めて、多重構造にできる。
その多重構造を ネスト という。
■繰り返し文の中断■
繰り返し文は、途中で中断することが出来る。
二種類の中断方法がある。
break文
繰り返し自体を中断する文。
continue文
その周だけ中断し、次の周にいく文。
この continue の使い方は、いまいちですね。
(例文がいまいちな仕上がりになってしまったので、もう少し勉強したい。)
ぱっとみて、わかりづらいコードは、業務では好まれないから、わかりやすいコードを書くことを目指すのがいいようです。
今回は、そのバリエーションについて学ぶ。
■while文■
while文 は2種類ある。
前々回、学習した、「while 文」の他に
「do - while文」というもの。
while文は、条件式を評価してから、ブロックを実行する。
判定結果が false の場合、一度もブロックが実行されない。
package blog; public class Shopping { // 所持金が足りる間は本を買い続けるプログラム public static void main(String[] args) { int money = 5000; System.out.println("あなたは" + money + "持っています"); int price = 5500; // 条件式は // 「money が price 以下の間は」 while (price <= money) { System.out.println(price + "円の本を買います"); // money -= price でも書けるけど、 // わかりづらいから業務ではやめたほうがいい money = money - price; System.out.println("残金は" + money + "円です"); } } }
一つ目の実行結果は、
price の値を 1980 円にしています。
二つ目は、money が足りていないので、何も実行されない。
do-while文は、ブロックを実行してから、条件式を評価する。
判定結果にかかわらず、最低一回は、ブロックを実行する。
package blog; public class Shopping2 { // 所持金が足りる間は本を買い続けるプログラム public static void main(String[] args) { int money = 5000; System.out.println("所持金は" + money + "円です"); int price = 5500; // 実行文 // 本を買って、所持金から値段分を引く do { System.out.println(price + "円の本を買います"); money = money - price; System.out.println("残金は" + money + "円です"); // 条件式 // 所持金がお金よりも低かったら } while (price <= money); } }
必ず、一度は実行されるので、実行結果2のように、
所持金が足りなくても、買い物をしてしまうので注意!!
do-while文は、それほど使わないので、あまり気にしなくてもいい。
■for文■
for文は、繰り返しの回数を指定するときに使う。
1,初期化処理
最初に一回だけ実行される文。
ここで使う変数をループ変数という。
変数名は、なんでもいいけど、通常は i など一文字にする。
すでに使用している変数名は使えない。(ブロック内では使える)
2,繰り返し条件
ブロックの内容を実行する前に評価され、このループを継続するか否かを判断する条件式
3,繰り返し時の処理
for文のブロックを最後まで処理した直後に、自動的に実行される文。
package blog; public class Dog { // 犬を数えるプログラム public static void main(String[] args) { // i が 95~105の間、ワンちゃんのカウントを続ける for (int i = 95; i <= 105; i++) { System.out.println(i + "匹ワンちゃん!!"); } } }
これは、非常に簡単な繰り返し文。
もう少し、複雑なコードを書ける。
■ネスト■
制御構造(条件分岐、繰り返し)は、その中に、別の制御構造を含めて、多重構造にできる。
その多重構造を ネスト という。
package blog; public class MultiplexStructure { // 9月末のジムに行く予定をだすプログラム public static void main(String[] args) { System.out.println("9月末は4日おきにジムに行きます"); // 21~30の間 for (int i = 21; i <= 30; i++) { System.out.println("今日は9月" + i + "日です"); // i が 4 で割り切れるときは(割って、余りの数が出ない状態) if (i % 4 == 0) { System.out.println("ジムに行く日です"); } } } }
■繰り返し文の中断■
繰り返し文は、途中で中断することが出来る。
二種類の中断方法がある。
break文
繰り返し自体を中断する文。
continue文
その周だけ中断し、次の周にいく文。
package blog; public class Interruption { public static void main(String[] args) { // 複雑な条件でジムに行く日を出すプログラム System.out.println("9月の予定を決める"); System.out.println("今月は、4日に一度ジムに行く"); System.out.println("12日と20日はお休み"); System.out.println("23日以降は、旅行でいない"); // 1~30 の間、繰り返す処理 for (int i = 1; i <= 30; i++) { System.out.println("今日は9月" + i + "日です"); // 23日以降は、旅行でいないので、以降の処理を中断する if (i == 23) { break; // 12日はお休みなので、処理を飛ばす } else if (i == 12) { continue; // 20日はお休みなので、処理を飛ばす } else if (i == 20) { continue; // 4日ごとにジムにいく } else if (i % 4 == 0) { System.out.println("ジムに行く日です"); } } } }
この continue の使い方は、いまいちですね。
(例文がいまいちな仕上がりになってしまったので、もう少し勉強したい。)
ぱっとみて、わかりづらいコードは、業務では好まれないから、わかりやすいコードを書くことを目指すのがいいようです。
2014年9月19日金曜日
- 分岐構文 - Java
前回、学習した分岐構文には、さまざまなバリエーションがある。
今日は、他のバリエーションについて。
■if 文■
if 文 は3種類ある。
前回、学習したのは 「if - else 構文」というもっとも基本の形。
あとは、「if のみ構文」、「if - else if - else構文」2種類。
一つずつみていく。
基本の形。
true と false で別々の処理を行う。
条件が満たされなかった場合に何もしない。
else の中のブロック内になにも書かない場合に else を省略できる。
2つめの実行結果は、条件が満たされなかったので、何も実行されない。
もし、条件が満たされなかった場合、別の条件で評価するときに使う。
1つの if 文で、3つ以上のルートに分岐できる。
■switch 文■
if 文をスマートな形で書くための文。
使える条件
・「変数 == 値」「変数 == 変数」のように、右辺と左辺が一致するかを比較する式のとき
・値が整数(byte型,short型,int型)、または文字(char型)のみ。
小数、文字列には使えない。
書く際の注意点
・ switch の直後に書くのは、条件式ではなく、変数名
・ case の横に 値 を書き、後ろに コロン(:)を書く。(;)と間違えないように!!
・ case 以降の末尾に break 文を忘れないように。
(書き忘れると、次の case文へ処理が進む!)
・ default:(デフォルトラベル)は、省略可能。
今日は、他のバリエーションについて。
■if 文■
if 文 は3種類ある。
前回、学習したのは 「if - else 構文」というもっとも基本の形。
あとは、「if のみ構文」、「if - else if - else構文」2種類。
一つずつみていく。
基本の形。
true と false で別々の処理を行う。
条件が満たされなかった場合に何もしない。
else の中のブロック内になにも書かない場合に else を省略できる。
package blog; public class OnlyIf { public static void main(String[] args) { System.out.println("あなたの年齢はいくつですか?"); // age(年齢) にキーボードから入力された整数を代入する命令 int age = new java.util.Scanner(System.in).nextInt(); // もし、 age(年齢) が 20 以上ならば if (age >= 20) { System.out.println("あなたは、お酒がのめます!"); } } }
2つめの実行結果は、条件が満たされなかったので、何も実行されない。
もし、条件が満たされなかった場合、別の条件で評価するときに使う。
1つの if 文で、3つ以上のルートに分岐できる。
package blog; public class PluralityConditi { // 猫の年齢で、成長過程かどうかを表示する public static void main(String[] args) { // 0~24 の整数をランダムで catAge に代入 int catAge = new java.util.Random().nextInt(25); System.out.println(catAge + "歳の猫がいます"); // catAge が 0 だったら if (catAge == 0) { System.out.println("猫はまだまだ成長期!!"); // catAge が 6 以下だったら } else if (catAge <= 6) { System.out.println("猫は、もう おとな だよ!"); // catAge が 16 以下だったら } else if (catAge <= 16) { System.out.println("猫は、もう 高齢 だよ!!"); // それ以外なら(17~24) } else { System.out.println("長寿!!!"); } } }
■switch 文■
if 文をスマートな形で書くための文。
使える条件
・「変数 == 値」「変数 == 変数」のように、右辺と左辺が一致するかを比較する式のとき
・値が整数(byte型,short型,int型)、または文字(char型)のみ。
小数、文字列には使えない。
書く際の注意点
・ switch の直後に書くのは、条件式ではなく、変数名
・ case の横に 値 を書き、後ろに コロン(:)を書く。(;)と間違えないように!!
・ case 以降の末尾に break 文を忘れないように。
(書き忘れると、次の case文へ処理が進む!)
・ default:(デフォルトラベル)は、省略可能。
package blog; public class Switch { // 日にちを入力したら、天気予報を出力する public static void main(String[] args) { System.out.println("9/19~23までの東京の天気予報です。"); System.out.println("いつの天気が知りたいですか?"); System.out.println("19~23の好きな日を入力してね!"); // day にキーボードから入力された数字を代入 int day = new java.util.Scanner(System.in).nextInt(); switch (day) { // day が 19 の場合は case 19: System.out.println(day + "日は、晴れのち曇りです"); break; // day が 20 の場合は case 20: System.out.println(day + "日は、曇りです"); break; // day が 21 の場合は case 21: System.out.println(day + "日は曇りのち雨です"); break; // day が 22 の場合は case 22: System.out.println(day + "日は曇りです"); break; // day が 23 の場合は case 23: System.out.println(day + "日は曇りのち晴れです"); break; // それ以外の場合 default: System.out.println("何も表示されない場合は、入力した数字が間違ってます。"); } System.out.println("同じ処理を if-else if-else 文で書きます"); // もしも、 day が 19のときは if (day == 19) { System.out.println(day + "日は、晴れのち曇りです"); // もしも、 day が 20のときは } else if (day == 20) { System.out.println(day + "日は、曇りです"); // もしも、 day が 21のときは } else if (day == 21) { System.out.println(day + "日は、曇りです"); // もしも、 day が 22のときは } else if (day == 22) { System.out.println(day + "日は、曇りです"); // もしも、 day が 23のときは } else if (day == 23) { System.out.println(day + "日は、曇りです"); // そうでなければ } else { System.out.println("何も表示されない場合は、入力した数字が間違ってます。"); } } }
登録:
投稿 (Atom)