JavaSilver_躓いた問題をまとめてみた④ 配列その1

f:id:nowa0402:20210524141506p:plain
こんにちは。のわです。
今回は、Javaの配列についてまとめたいと思います。


最初に配列の基本的なルールについてまとめます。
先に今回のポイントを記述します。

 ・配列定義時は要素数・または要素を明確にする
 ・変数宣言に要素数を入れない

実際のコードを見ながら確認していきます。



配列の生成方法にはいくつかパターンがあります。

public class Main {
	public static void main(String[] args) {
   
   // パターン1 配列インスタンスを生成後に要素を代入する
   int[] array1 = new int[2]; 
   array1[0] = 1;
   array1[1] = 2;
   for(int i : array1) {
       System.out.println(i);
   }
   
   // パターン2 配列インスタンス生成と同時に要素を代入する
   int[] array2 = new int[]{3,4};
   for(int i : array2) {
       System.out.println(i);
   }
   
   // パターン3 パターン2を簡略化したもの
   int[] array3 = {5,6};
   for(int i : array3) {
       System.out.println(i);
   }
   
   //パターン4 配列変数を宣言してから、配列インスタンスを生成
   int[] array4;
   array4 = new int[]{7,8};
   for(int i : array4) {
       System.out.println(i);
   }
   
 }
}

コードの解説です。
このコードでは、4つのパターンで配列を生成しています。
生成した配列に要素を入れ、for文で一個ずつ取り出して出力するものです。

記述方法はそれぞれ違いますが、やっていることは一緒です。



なお、配列を記述する際に使われる『[]』大カッコですが、変数名のあとにつけても大丈夫です。
Java以外の言語から来た人でも、柔軟にコードをかけるようにしている為だそうです。

public class Main {
	public static void main(String[] args) {
      
   // パターン5 パターン3の大カッコを変数のあとにつける
   int array5[] = {9,10};
   for(int i : array5) {
       System.out.println(i);
   }
   
 }
}

ここで注意したいのが
どのパターンも『配列インスタンス生成時、要素数・または要素が確定している』ことです。
つまり、配列インスタンスを生成するとき
『要素数がいくつ入っているか不明だとコンパイルエラー』になります。


実際のNGコードでみてみます。

public class Main {
	public static void main(String[] args) {
   
   // NGパターン1 配列宣言時に要素数が確定していない
   int[] arrayNg1 = new int[];

 }
}

このコードでは配列インスタンス生成時に素数を確定させていません
そのため、コンパイルエラーになります。

もう一つ別の例をみてみましょう

public class Main {
	public static void main(String[] args) {
   
   // NGパターン2 要素数と要素を同時に定義している
   int[] arrayNg2 = new int[2]{1,2};

 }
}

このパターンは配列インスタンス生成時に要素数と要素どちらも定義しています。
配列インスタンス生成時は『要素数または要素どちらかを明確にする』ことになっています。
そのため、どちらも定義しているとコンパイルエラーになります。



次に、ちょっと特殊なコードを紹介します。

public class Main {
	public static void main(String[] args) {
   
   // パターン6 要素数が0の配列を生成する その1
   int[] array6 = new int[0];
   
   // パターン7 要素が無い配列を生成する その2
   int[] array7 = {};
   
 }
}

この配列は要素数が0、要素が無い配列を生成しています。
一見するとコンパイルエラーになりそうです。


こちらのコード、実はコンパイルが通ります。
なぜなら
『要素数が0と明記されている配列』
『要素が無いと明記されている配列』

であり、配列定義の要件を満たしているからです。

ただし、この配列はなんの意味も持ちませんけど...



次に、別なNGコードです。

public class Main {
	public static void main(String[] args) {
   
   // NGパターン3 配列変数側に要素数を入れている
   int[2] arrayNg3 = {5,6};

 }
}

このNGパターンは配列宣言側に要素数を入れています。
変数宣言側は『私はこういった型です』といった宣言をするものです。
そのため、変数宣言側に具体的な数値をいれるとコンパイルエラーになります。




次に多次元配列についてまとめます。
多次元配列は『配列の中にさらに配列がある』状態です。
実際にコードを見てみましょう。

public class Main {
	public static void main(String[] args) {
   
   // 多次元配列パターン1
   int[][] arrays1 = new int[2][3];
   arrays1[0] = new int[]{1, 2, 3};
   arrays1[1] = new int[]{4, 5, 6};
   for(int[] i : arrays1) { //1次元目の配列を取り出す
        for(int ii : i) { //2次元目の配列を取り出す
            System.out.println(ii);
        }
   }

   // 多次元配列パターン2
   int[][] arrays2 = new int[][]{{7, 8, 9}, {10, 11, 12}};
   for(int[] i : arrays2) { 
        for(int ii : i) { 
            System.out.println(ii);
        }
   }
   
 }
}


多次元配列も変数宣言の[]大カッコはどこに置いても大丈夫です

public class Main {
	public static void main(String[] args) {
   
   // 多次元配列パターン3 大カッコの場所が変わった
   int[] arrays3[] = new int[2][3];
   arrays3[0] = new int[]{1, 2, 3};
   arrays3[1] = new int[]{4, 5, 6};
   for(int[] i : arrays3) { 
        for(int ii : i) { 
            System.out.println(ii);
        }
   }

   // 多次元配列パターン4
   int arrays4[][] = new int[][]{{7, 8, 9}, {10, 11, 12}};
   for(int[] i : arrays4) { 
        for(int ii : i) { 
            System.out.println(ii);
        }
   }
   
 }
}


多次元配列の特徴として、
『1次元配列の要素数が決まっていれば2次元要素数は不明でもOK』というルールがあります。
それが次のコードです。

public class Main {
	public static void main(String[] args) {
   
   // 多次元配列パターン5 生成時に1次元だけ宣言しておく
   int[] arrays5[] = new int[2][];
   arrays5[0] = new int[]{1, 2, 3};
   arrays5[1] = new int[]{4, 5, 6};
   for(int[] i : arrays5) { //1次元目の配列を取り出す
        for(int ii : i) { //2次元目の配列を取り出す
            System.out.println(ii);
        }
   }

 }
}


上記コードの場合、1次元配列の要素数だけ先に決め
その後で2次元配列の要素を入れています。


なお、その逆はコンパイルエラーになります。

public class Main {
	public static void main(String[] args) {
   
   // NG多次元配列パターン 生成時に2次元だけ宣言しておく
   int[] arraysNg[] = new int[][3];

 }
}




今回は配列についてまとめました。
 おさらいです
 ・配列生成時は『要素数または要素が決まっている』状態にする。
 ・要素数0、要素が無い配列を作成することも可能
 ・多次元配列は『1次元配列の要素数が決まっている』ことが生成の条件


JavaSilverの勉強をしていて一番理解が足りていない箇所だと痛感しまとめてみました。
配列を理解したい方への助けになれば幸いです。


今回も最後まで読んでいただきありがとうございました!!

JavaSilver_躓いた問題をまとめてみた③ 例外処理その2

f:id:nowa0402:20210520184724p:plain

こんにちは。のわです。
今回は現在勉強中のJavaSilverから
例外について引き続きまとめたいと思います。

前回の記事で簡単に構文について記載しました。
nowa-0402.hatenablog.com


今回は例外の伝播と例外を発生させる方法について記述します。


例外の伝播とは
「あるメソッドが違うメソッドを呼び出したとき
 そのメソッドで例外が発生し、例外処理されなかった場合
 呼び出し元まで例外がたらい回しにされる状況」
のことです。

言葉だと長いですね...
例えば mainメソッドがsubメソッドを呼び出すコードを例にしてみましょう。

public class Main{
  public static void main(String[] args) {
    sub();
    System.out.println("処理を終了します");
  }

  public static void sub() {
    String a = null;
    System.out.println(a.length());
  }
}

上記コードでは
①mainメソッドがsubメソッドを呼び出す
②subメソッドは変数aに入っている文字列数を出力する
③「処理を終了します」と出力される

しかし、subメソッドの変数aにはnullが入っています。
lengthメソッドでnullを参照しようとしているため
② の処理中に「NullPointerException」の例外が発生します。


この時、上記コードでは何が起きるか
①subメソッドは発生した例外をキャッチしようとするが、try-catch文が無いためキャッチできない
②キャッチ出来なかった例外をmainメソッドにわたす
③mainメソッドはsubメソッドから例外が来るが、try-catch文がないためキャッチできない
④誰もキャッチできずプログラムが強制終了する


という処理になっています。
まさに「例外がたらい回し」にされている状態です。
「処理が終了します」までたどり着けませんでした。


上記のような単純なコードなら強制終了でもいいですが
インフラシステムのようなプログラムで簡単に強制終了されたら大変なことになりますね。。。


では、どうすればよいか
解決策は2つです。
①subメソッドが例外を処理する
②呼び出し元のmainメソッドが処理する

①subメソッドが例外を処理する。
この場合だと下記の様なコードになります。

public class Main{
  public static void main(String[] args) {
    sub();
    System.out.println("処理を終了します");
  }

  public static void sub() {
    try{
    String a = null;
    System.out.println(a.length());
    } catch(NullPointerException e) {
      System.out.println("エラーが発生しました");
    }
  }
}

このとき、subメソッドは『自ら起こした例外を自ら処理する』状態ともいえます。



②呼び出し元のmainメソッドが処理する
だとどうなるでしょうか。

public class Main{
  public static void main(String[] args) {
    try {
    sub();
    } catch (NullPointerException e) {
      System.out.println("subメソッドで異常が発生しました");
    }
    System.out.println("処理を終了します");
  }

  public static void sub() throws NullPointerException{
    String a = null;
    System.out.println(a.length());
  }
}

見慣れないワードが出てきました
『throws』はスロー宣言と呼ばれるものです。
この宣言をしているメソッドはtry-catch文の記述をしなくても良くなります。
その代わり、スロー宣言をしているメソッドを呼び出す側でtry-catch文を使う必要があります。

簡単にいうなら
「私を呼び出して何かあったら、呼び出したあなたが責任持って処理してくださいね」
という状態です。


※上記コードですが、try-catch文を必ずしも書く必要は無い例外です。
 try-catchが必須なのはException系になります。
 NullPointerExceptionRuntimeException系と呼ばれる例外種類になります。
 この例外は必ずしもtry-catch文を書く必要がないものです。
 今回は簡単コードを記述するためにRuntimeException系を例にあげました。



では、次に例外を自力で発生させる方法を見ていきましょう。

public class Main{
  public static void main(String[] args) {
    String a = null;
    if(a == null) {
      throw new NullPointerException("値がnullです");
    }
  }
}

『throw』は『例外的状況の報告』をする構文になります。
上記コードの場合
throw new 例外クラス("任意のエラーメッセージ")
という記述になります。

この例外的状況の報告は「私達がJVMに例外を知らせるコード」です。
逆に、今まで記述してきた例外は「JVMが私達に例外を知らせるコード」でした。
これを『例外を投げる』といいます。



今回は例外についてまとめてみました。
 要点のまとめです。
◇例外が発生する可能性がある処理をおこなうとき以下のどちらかで対応する必要がある
  ・呼び出し先でtry-catch文を記述する
  ・呼び出し先でスロー宣言(throws)を行い、呼び出し元で例外を処理させる

◇例外を投げるためにはthrow 文を使う

今回も最後まで読んでいただきありがとうございました!!





以下余談です。

JavaSilver用です。
例外の伝播は永遠にたらい回しにすることができます。

public class Main {
  public static void main(String[] args) {
      try{
      sub();
      } catch(Exception e) {
        System.out.println("異常発生");
      }
      System.out.println("処理を終了します");
  }

  public static void sub() throws Exception {
    System.out.println("subsubメソッドを呼び出します");
    subsub();
  }

  public static void subsub() throws Exception {
    System.out.println("例外を作り出します");
    throw new Exception("例外です");
  }

}

Exception系の例外はどこかしらでキャッチする必要があります。
このコードでは例外処理をmainメソッドで行っています。

では、下記コードはどうでしょうか

public class Main {
  public static void main(String[] args) throws Exception{
      sub();
      System.out.println("処理を終了します");
  }

  public static void sub() throws Exception {
    System.out.println("subsubメソッドを呼び出します");
    subsub();
  }

  public static void subsub() throws Exception {
    System.out.println("例外を作り出します");
    throw new Exception("例外です");
  }

}

上記コードを見ると最終的な呼び出し元のmainメソッドもスロー宣言をしています。
この場合、コンパイルエラーになりそうですが、ならずに実行することができます。
ただし、「処理を終了します」まで処理が行われる前に強制終了になります。


うーん...例外って難しいですね...

JavaSilver_躓いた問題をまとめてみた② 例外処理その1

f:id:nowa0402:20210520184724p:plain

こんにちは。のわです。
今回は現在勉強中のJavaSilverから
例外についてまとめたいと思います。


例外とはなにか
一言でいうなら『プログラム実行中に想定外の状況になる』という現象です。

そして、例外処理とは
『例外に対する対策』をすることです。

早速コードを見てみましょう。

import java.io.*;

public class Main {
  public static void main(String[] args) {
    try {
      FileReader fw = new FileReader("date.txt");
    } catch (IOException e) {
      System.out.println("エラーが発生しました");
      System.out.println(e);
    }
  }
}

例外の基本文法は「try-catch」文です。
try文が通常処理
catch文が例外発生時の処理内容になります。

上記コードの解説です。
FileReaderを使用し、date.txtのファイルを読み出そうとしています。
このコード自体は問題がないのでコンパイルエラーとはなりません。

例外が発生するのは実行時です。

プログラムを実行した際、try文の中を処理しします。
プログラムはdate.txtを読み出します。
その時、date.txtが存在しないと例外発生となります。
(java.io.FileNotFoundException: date.txt (No such file or directory))

上記例外が出た際に、プログラムはcatch文に移行します。
catch文の構文は以下のとおりです。
catch(例外クラス 変数名)

変数名には例外内容が入ります。(今回だとFileNotFoundException)
その後は任意の処理内容を記載します。

では、次に上記コードに文を追加しましょう。

import java.io.*;

public class Main {
  public static void main(String[] args) {
    try {
      FileReader fw = new FileReader("date.txt");
    } catch (IOException e) {
      System.out.println("エラーが発生しました");
      System.out.println(e);
    } finally {
      System.out.println("処理を終了します");
    }
  }
}

finallyという文が追加されました。
finallyは「必ず処理される文」です。

try文で例外が発生するとcatch文に移行するのは先程解説いたしました。
catch文で処理されたあと、プログラムは強制終了となるため
後片付けの処理ができなくなります。

この時に使用するのがfinally文です。
finally文は必ず処理される内容を記述します。
必ず処理されるので
 ・try文がうまく行った場合
 ・try文で例外が発生した場合
の二段階の対応が可能になります。


今回は例外処理についてまとめてみました。
 ・例外とは「プログラム実行中に想定外の事態が発生した状況のこと」
 ・例外を処理する文法は「try-catch」文
 ・必ず処理させたい内容は「finally」文に記述

次回は例外処理の具体的な内容をまとめたいと思います!
今回も最後まで読んでいただきありがとうございました!

JavaSilver_躓いた問題をまとめてみた① コンスタントプール

f:id:nowa0402:20210514162016p:plain

こんにちは。のわです。
今回からしばらくの間、現在勉強中のJavaSilverから躓いた問題をまとめてみたいと思います。
第一回目はコンスタントプールです。



早速ですが、問題です。

  String a = "abc";
  String b = "abc";
  System.out.println(a == b);

上記コードを実行時、出力結果は何になるでしょうか。





答えは【true】です。
私は【false】だと思っていました。


では下記コードだとどうなるでしょうか。

  String a = "abc";
  String b = new String("abc");
  System.out.println(a == b);





答えは【false】です。
この違いはなんでしょうか。




解説です。

なぜ私が最初のコードの実行結果を【false】だと思っていたのか。
それは『String 変数 = "文字列";』を、都度Stringインスタンスが生成されているものだと勘違いしていたからです。

私の脳内イメージは
「Stringでaとbを別々に生成されたインスタンス
「a == bは同じインスタンスかどうかみているから答えはfalse」

となっていました。

通常の考え方であれば上記の認識で間違いはありません。
ただ、Stringは違っていたのです。
では、Stringインスタンス生成時の特別ルールとはなにか。
キーワードは『コンスタントプール』になります。

コンスタントプールは
『コード中に同じ文字列リテラルが登場した場合、Stringインスタンスへの参照先が使いまわしされる仕組み』
になります。

言い換えるなら
『同じ言葉で格納されたStringインスタンスは同じ参照先をみている=同一インスタンス
となります。

なぜコンスタントプールが存在するのか
文字列リテラルはプログラム上にたくさんでてきます。
そのため、同じ文字列を何度も生成するのはメモリをたくさん使う羽目になります。

上記理由から
「同じ文字列だったら、できる限り使いまわししてメモリ処理を軽減させようね」という目的で存在しているわけです。


では、もう一度最初のコードをみてみましょう。

  String a = "abc";
  String b = "abc";
  System.out.println(a == b);

この問題では同文字列リテラルインスタンスを2つ生成しています。
上記解説に当てはめるなら『String b はString aと一緒の文字列だから、参照先を一緒にしている』状態です。
そのため、最後の同一判定でtrueとなるわけです。



そうすると違う疑問が出てきます。
なぜ、2つ目のコードでは【false】になるのでしょうか

  String a = "abc";
  String b = new String("abc");
  System.out.println(a == b);


この場合、String bはnew演算子インスタンスを生成しています。
new演算子で明示的にインスタンスを生成すると
コンスタントプールを参照せずに、インスタンスを生成することができます。

つまり、String a でabcの文字列リテラルはコンスタントプール内に出来ているのですが
String bではコンスタントプールを参照しないで生成している状態です。

上記理由からSting a とString b は参照先が異なるインスタンスになるため【false】になります。





では、次に先程のコードにあるメソッドを追記します。
この場合、答えはどうなるでしょうか。

  String a = "abc";
  String b = new String("abc");
  System.out.println(a == b.intern());


この場合、答えは【true】になります。
intern()メソッドは『コンスタントプールを含むメモリ内の文字列を探して再利用する』メソッドです。
因存在しない場合は、文字列をコンスタントプールに登録したのち、その登録先を参照先として格納します。


このことから、b.intern()で何が行われているか
b,intern()によって
『bに格納されている文字列をコンスタントプール含むメモリ内から検索し、あればその参照先を戻り値とする』
という処理が行われています。

この場合の文字列は「abc」
「abc」はString aが先にコンスタントプールに登録しています。
そのため、b.intern()にはString aと同じ参照先が格納されるため同一参照先をみることになります。
結果
『a == bは異なる参照先だから【false】』
『a == b.intern()はbの参照先がaと同じになったので【true】』

になります。



今回のまとめです。

 ◇コンスタントプールとは『文字列を保存し、同文字列出現時、使い回しできるようにする仕組みのこと』
 
 ◇Stringインスタンス生成時の右辺への記載を
  ・文字列だけにする⇒コンスタントプールの対象
  ・new演算子で明示的にする⇒コンスタントプールの対象外
 
 ◇intern()メソッドの機能『コンスタントプールを含むメモリ内の文字列を探す』
  ・あればその文字列の参照先が戻り値となる
  ・なければ文字列をコンスタントプールに登録した後、そこを参照先して戻り値を返す



今回も最後まで読んでいただきありがとうございました!

【備忘録】Java_リテラル

f:id:nowa0402:20210508180533p:plain

こんにちは。のわです。
今日はJavaからリテラルについてまとめたいと思います。


リテラルとはソースコード中に記述する値』のことです。

  int i = 10;

上記コードの「10」がリテラルになります。

そして、リテラルはデータ型を持っています。
上記コードの「int」が型になります。

このデータ型とリテラルには書き方に一定のルールがあります。
ざっとまとめてみました。

 int i = 10; // 整数
 long l = 100000L; // int型より大きい整数 末尾に「L」もしくは「l」をつける
double d = 3.14; // 小数点付きの数字
float f = 3.14F; // 小数点付きの数字 末尾に「F」もしくは「f」をつける
boolean b = true; // 真偽値 入る値は「true」か「false」
char c = 'A'; // 1つの文字 「'」で囲む 

int型とchar型は以下のような宣言も可能です。

  int a = 0x11; //「0x」で16進数表記 aには17が入る
  int b = 011; // 「0」で8進数表記 bには9が入る
  int c = 0b0011; //「0b」で2進数表記 cには3が入る

 char d = 12354; // Unicode表記 dには「あ」が入る
 char e = '¥u3042'; // Unicode 16進数表記 eには「あ」が入る

ここからが応用編、リテラルには任意の場所にアンダースコア(_)を入れることが可能です。
ただし、以下の条件をクリアすることが必要です。
 条件①リテラルの先頭と末尾にはつけられない
 条件②記号の前後には記述できない
ここでいう記号は「.」「L」「F」「0b」「0x」などのリテラル内で記述できるものです。

いくつか例をあげてみます

  int a = 1_000_000; // OK
  int b = _100; // NG 条件①
  int c = 100_; // NG 条件①
  int d = 0_1100; // OK
  int e = 0x_11; // NG 条件②
  float f = 3.14_F; // NG 条件②
  double g = 3._14; // NG 条件②

となります。

今回はリテラルについてまとめてみました。
次回はデータ型と変数についてまとめたいと思います!

最後まで読んでいただきありがとうございました!

【備忘録】Java_コレクション

f:id:nowa0402:20210505160433p:plain
こんにちは、のわです。
今回は勉強中のJavaからコレクションについて備忘録を残します。

前回の記事で勇者VSドラゴンの記事をあげました。
nowa-0402.hatenablog.com

そこから下記内容を追加して現在プログラム修正中です。
 ・職業魔法使いを増やす。
 ・モンスターを増やす

魔法使いを増やしたことで勇者はパーティを組む必要が出てきました。
そこで、勉強したコレクションを使ってパーティ化することにしました。

※前提
 勇者=Heroクラス
 魔法使い=Wizardクラス
 勇者と魔法使いの親クラス=Characterクラス

【Main.java

    // ArrayListの記述省略のためimportしておく
    import java.util.*:

    // 勇者と魔法使いを生み出す
    Character c1 = new Hero();
    Character c2 = new Wizard();
    // 勇者と魔法使いでパーティを組む
    ArrayList<Character> party = new ArrayList<>();
    party.add(c1);
    party.add(c2);

コレクションと配列の違う点は要素を随時追加できる点です。

   // Character型のコレクション『party』を作成
    ArrayList<Character> party = new ArrayList<>();
 // partyに対して勇者と魔法使いのインスタンスを格納
    party.add(c1);
    party.add(c2);

上記で言うところの『.add()』メソッドが追加の役割を果たしています。
配列は事前にいくつ入れるのか決める必要があり
そこから要素を追加することは出来ませんでした。

コレクション(ArrayListの場合)だと
 ・要素追加は『.add(インスタンスの型)』
 ・要素削除は『.remove(int)』
と楽に追加、削除や取り出しが可能です。


では、コレクション化すると何が出来るようになるか。
実際にコレクションを活かしたプログラムを作ってみました。

【Main.java

    import java.util.*;

    // 勇者と魔法使いを生み出す
    Character c1 = new Hero();
    Character c2 = new Wizard();
    // 勇者と魔法使いでパーティを組む
    ArrayList<Character> party = new ArrayList<>();
    party.add(c1);
    party.add(c2);

   // ドラゴンを生み出す
   Dragon d = new Dragon();

  // ドラゴンがパーティに火を吹く
   d.fireBless(party);


【Dragon.java

 // ドラゴンがパーティに火を吹く
  import java.util.*;

  public void fireBless(ArrayList<Character> party) {
    System.out.println("ドラゴンは全体に火を吹いた!");
    for(int i = 0; i < party.size(); i++) {
      party.get(i).hp -= 20;
      System.out.println(party.get(i).name + "は20ポイントダメージを受けた!");
    }
  }

コレクションはデータ型、配列と同様、引数に指定することが可能です。
実際、どんな処理をしているのか簡単に説明します。

  public void fireBless(ArrayList<Character> party) {}

メソッドの引数にコレクションを指定しています。
変数名は任意の名前をつけます。
今回はMain.javaで付けたpartyにしています。

for(int i = 0; i < party.size(); i++) {
   party.get(i).hp -= 20;
   System.out.println(party.get(i).name + "は20ポイントダメージを受けた!");
    }

今回のポイントになります。
引数でもらった勇者御一行にどうやってダメージを与えるか
下記で詳細を説明します。

 for(int i = 0; i < party.size(); i++) {}

for文で何回繰り返すか設定しています。
『.size()』メソッドは格納されている要素数を返します。
今回、要素数は勇者と魔法使いの2人です。
つまり、『i < 2』となり、iが2になったら処理が終了します。

    party.get(i).hp -= 20;
    System.out.println(party.get(i).name + "は20ポイントダメージを受けた!");

この文でダメージを与えています。
『.get(int)』メソッドはint番目の要素を取り出します。
つまり、『party.get(i).hp -= 20;』は
『partyのi番目にいるキャラのHPを20引け』
という意味になります。
iはfor文で定義しています。
 ・繰り返し1回目なら『i = 0』となり、勇者が対象
 ・繰り返し2回目なら『i = 1』となり、魔法使いが対象
になります。

因みに、コレクションは配列と同じく要素は『0』から始まります。
『1』からでは無いので注意してください。



今回はコレクションを使ったプログラムを紹介しました。

私自身、コレクションを勉強した当初は
「何に使えるのこれ」という感じでした。
ですが、コードを書きながら、色々試行錯誤をしていくうちに
「色々できるやん!コレクションすごい!」と気づきました。

やっぱり、考えながらコードを書くのが一番楽しくて、勉強になりますね。


なお、コレクションは引数だけではなく、戻り値にも指定できます。
是非活用してみてください!

今回も最後まで見ていただきありがとうございました!

【備忘録】Linux_LPIC認定試験を通じて得たもの

f:id:nowa0402:20210430153910p:plain
 こんにちは。のわです。
f:id:nowa0402:20210430142631j:plain
 本日(2021/4/30)にLPIC102を取得しました!
 前回の101と合わせ、無事LPIC1認定取得できました。

 今回はLPIC試験を通じて勉強になったことを記録したいと思います。

※勉強方法についてはLPIC101取得と同じように進めました。
もし参考にされたい方は下記の記事を参照ください。

nowa-0402.hatenablog.com


 私が身についたなと思うものは2点
  Linuxの基礎知識を理解することができる】
  【CUI操作に慣れる】

 これらについてまとめていきます。


※本題前に
  LinuxとはWindowsmac OSと同じオペレーションシステムの一つです。
 大きな特徴は『無料で使用することができること』です。

  では、なぜ私はLinuxを学ぶことにしたのか
 それは『サーバで数多く利用されている』からです。
 
  Linuxは上記の通り『無料』でOSを使用することができます。
 サーバを数多く運用するのであれば、OSは費用がかからないLinuxを選択する可能性が高くなります。
 私は、エンジニアを目指すのであればサーバ側の知識が必要になると考えていました。
 そのため、Linuxの知識を身につけようとしたのです。


LPIC試験を通じて得たもの①
Linuxの基礎知識を身につけることができる】
  Linuxをどう学ぶか、私は色々考えました。
 Linuxを学ぶといっても、何をどう学べばいいのか分かりませんでした。
 そこで思いついたのが『LPIC』の認定試験でした。
 
  LPICレベル1認定を目指す。そして、その過程でLinuxの基礎知識を身につけようとしました。
 私はLinuxを勉強するうえで
 ・動画教材の『Udemy』
 ・完全無料の教材『Linuxの標準教科書』
 ・LPIC資格本
 を使用し、勉強をすすめました。
  上記の中でLinux標準教科書』はLinuxを勉強したい方に是非取り組んでほしいです。
 無料教材ですが、有料級の情報がつまっています。
 リンクを載せておきますので参考にしてください。
 Linux標準教科書 ダウンロード LinuCレベル1対応 | Linux技術者認定試験 リナック | LPI-Japan

  結論、『何となく概要は把握した』状態になりました。
 当初は『OSなのは知っている』状態だったので、それなりに進歩したかなと思っています。
 後は、ポートフォリオを作成する際にサーバ構築等が必要になると考えています。
 そのタイミングで更にアウトプットして知識を定着させます。




LPIC試験を通じて得たもの②
CUI操作に慣れる】
  CUIというのはこんな画面で色々コマンドを打つことです。(画像はWindows)
 f:id:nowa0402:20210430154421p:plain
  個人的にこっちの方が得たものは大きかったです。
  Linuxに限らず、エンジニア転職に向けて勉強していると、CUI操作が求められる場面が多々あります。
 特にLinuxの勉強はCUI操作が基本になります。
 つまりCUI操作はエンジニアになるためには避けて通れない道』だと思いました。

  Linuxの勉強中、最初は訳もわからず教科書通りにコマンドを打つ状態が続きました。
 コマンドを打つと英語がずらっと出てきます。なんて書いてあるかまったく分かりません。
 これが一番つらかったです。CUIじゃなくてGUI(いつも使っているデスクトップ環境)を見ると安心します。
 
  ただ、毎日勉強していると、自然とディレクトリ移動やファイル作成、エラーに対する対応ができるようになってきます。
 こうなってくるとCUI操作が嫌じゃなくなってきます。
 『英語たくさんの画面に慣れてきた状態』になります。 
 
  CUIに慣れてくると、Linuxに限らず、プログラミング学習でも効果が出ています。
 CUIでたくさん経験する『コマンドを叩くと画面に出てくるたくさんの英語』
 ここから必要な情報を読み取る力が少しづつ身についてきました。

  結論、CUI操作を通じて
 『英語の羅列に苦手反応が出にくくなる』
 『出てきた情報から必要なものを取り出す』

 この力を身につけることができました。
 ただ、まだまだ理解が足りないと感じているので実践の中で成長していきます。
  CUI画面が苦手だと感じている方、是非Linux学習を通じて勉強してみてほしいです。
 


 今回はLPIC認定試験を通じて得たものについて記載しました。
  【Linuxの基礎知識を理解することができる】
    ・サーバ構築で必須となるLinuxを資格勉強を通じて身につける。
  【CUI操作に慣れる】
    ・英語がたくさん出てきても苦じゃなくなる
    ・必要な情報を読み取って検索する力が身につく

  認定試験に合格したからなにか人生が変わるものではないと思っています。
 しかし、勉強する目的が
  ・『合格のため』に勉強する
  ・『何を得たいのか』にフォーカスして勉強する
 どちらにするのかで、理解力に差が出るはずです。
  
  私の場合、『Linuxとはなにかを理解する』ことにフォーカスして勉強しました。
 理解する手段としてLPIC試験というわかりやすい道筋を立てました。
 なにか挑戦するときは『これをすると何が変わるのか』を考える。
 これを今後も大事にしていきたいと思います。
 
  今回も最後まで読んでいただきありがとうございました!