Java Silver 2章　変数と配列

#リテラル
リテラル：コード中に直接書き込む値
javaには4つのリテラルがある
・整数(int型が整数のデフォルト)
・浮動小数点数(double型が小数のデフォルト)
・真偽(boolean)
・文字(char)

これ以外のリテラルを明示する場合は下記のルールに従い接頭辞、接尾辞を付ける

```java
public class Main {
    public static void main(String[] args) {
      //整数リテラルの表現方法：10進数以外の表現は下記のルールに従う
      System.out.println(255);         // 10進数（整数値）：普通に表記
      System.out.println(0b11111111);  // 2進数：先頭0b
      System.out.println(0377);        // 8進数 :先頭0
      System.out.println(0xff);        // 16進数:先頭0x

      //浮動小数点数リテラルの表現方法
      System.out.println(12.33);       // 10進数(小数):普通に表記
      System.out.println(3e4);         // 指数：3.0 × 10の4乗

      //文字型リテラルの表現方法
      System.out.println('A');         // 1文字：1文字だと''
　　　System.out.println("Hello");     // 複数文字は""で囲う

      //Unicodeによる文字表現：世界中の言語に数値が割り振ってある
      System.out.println('\u3012');    // u+ 16進数4桁の整数で1文字(0～65535:16bit)
      System.out.println('45662');     // 10進数0～65535までの整数でも可能

      System.out.println(true);        // 論理値:そのまま
    }
}

```
リテラルはデータ型の宣言、代入なしでコード上で使用できる
変数のように値や状態を保持することができない

#変数
変数はリテラルと違い代入により処理結果や値を保持できる
保持するデータ型を明示する必要がある

識別子：変数やメソッドの名前
・予約語（Javaの中で既に定められた特別な名前）は識別子として使用不可
・"_"と"$"以外は使用できない
・数字から始めてはいけない

```java
public class Type {
 public static void main(String[] args){
   byte  b = 10;      //8bit整数
   short s = 20;      //16bit整数
   int   i = 30;      //32bit整数（整数値のデフォルト）
   long  l = 40L;  　 //64bit整数
   float f = 1.15F;   //32bit単精度浮動小数点数（小数値のデフォルト）
   double  d = 5.78;  //64bit倍精度浮動小数点数
   char  c = 'A';     //単数文字''で囲う
   string s = "string"//複数文字""で囲う
   boolean o = true;
   // final + 定数名  = 初期値
  }
}
```

変数はデータ型の違いによって2つに大別される
・基本データ型（プリミティブ型）：値そのものを扱う
・参照型：値、インスタンスのある場所（データ領域）への参照を扱う

データ型を明示しない場合、整数値、小数値の代入先の変数はそれぞれデフォルトとなる
その際、データ型の容量を超える数値の場合はエラーとなる

####桁あふれの検証
```java
public class Ling {
 public static void main(String [] args) {
    int m = 2147483647;
    System.out.println(m + "：int型最大値(32bit)");
        
    m += 1;
    System.out.println(m + "：+1して桁あふれ");
    
    long n = 2147483647;
    System.out.println(n + "：lomg型最大値(64bit)");
    
    n += 1;
    System.out.println(n + ":+1して桁あふれ");
  }
}
```
実行結果

```
PS C:\Users\Github\Java\05> java Ling      
2147483647：int型最大値(32bit)
-2147483648：+1して桁あふれ
2147483647：lomg型最大値(64bit)
2147483648:+1して桁あふれ
```
Int型（最大32bit）Long型（最大64bit）これを超えるとオーバーフローする。
基本情報技術者の時に仕組みだけ知ったが実践してみると面白い

－に転じるのは負の数を補数表現しているからだと思われる

###アンダースコア（ _ ）
桁数の多いリテラルを見やすくする
・リテラルの先頭、末尾は不可
・記号の前後は不可

#null
参照先がない状態を表すリテラルの一種であるため、参照型データにしか代入できない
基本データ型に代入するとエラーとなる

#変数のスコープ
変数のスオープ（有効範囲）
・ローカル変数：メソッド内で定義した変数（変数のスコープはメソッド内のみ）
・メンバ変数：クラス定義の直下で宣言した変数（基本的にプログラムのどこでも有効）
　　　　　　　修飾子により色々な属性を付加する

#ローカル変数の型推論（var）
変数宣言時にデータ型の代わりに"var"を使用すると、右辺の値からデータ型を推論する
変数が初期化されていない状態（空）であったり、nullだとデータ型を特定できない
ローカル変数の宣言でしか使えない（メソッドで宣言する変数）

```java
public class Main {
  //var a = 100;            // コンパイルエラー
  //static var b = 100;     // コンパイルエラー
 
 public static void main(String[] args) {
    var c = "hello";        // OK
    var d = 100;            // OK
    //var e;                // コンパイルエラー
    //var f = null;         // コンパイルエラー
    final var g = 100;      // OK
    //var final h = 100;    // コンパイルエラー
  }
}
```


#配列の作り方
```java
public class Array {
 public static void main(String[] args) {
  
  // データ型[] 配列名; 配列宣言
  
   // 配列の宣言:設計図の段階（何を入れる、何ていう名前の箱？）
   char[] c; //文字データを入れるCという名前の配列の設計図を作製
  
   // 配列の作成：実際に箱を作る段階（その箱の容量はどのくらい？）
   c = new char[3]; //cという名前の配列設計図（データ型）から実際に文字が3つ入るcという箱を作製 （領域確保）
      
   // 設計図の名前Cと実際の箱の名前cは必ず一緒になる？
  
  
  
   // 配列の宣言と作成を同時に行う
   int[] i = new int[3];
　 //数値を入れるiという名前の箱の設計図に、数字が3つ入る容量を確保した箱を作製
      
   // やはり設計図の名前iと実際の箱の名前iは必ず一緒になるか…
  
   // 各要素へ値の代入
   c[0] = 'A'; c[1] = 'B'; c[2] = 'C';       // 各要素へ値の代入
   i[0] = 100; i[1] = 200; i[2] = 300;      
 // iという箱にある3つの区画を指定（配列名[インデックス]）して代入
  
  
   // 宣言と作成と初期化を同時に行う
   String str[] = {"Welcome ","to ","Java."};
　// strという文字列の入る箱の設計図から3つの区画がある箱を作って、それぞれに初期文字列を設定
  
  
   System.out.println("strのサイズ: " + str.length);// 配列の要素数
   System.out.println("c[0]       : " + c[0]);
   System.out.println("i[1]       : " + i[1]);
    }
  }

```
ここはかなり時間をかけました。
jsやphpでは変数の宣言はクラス外でも可能で
変数の宣言とインスタンスの作成は特に意識しなかったです。

Javaではクラスとオブジェクトを明確に分けるために 
new を使い、インスタンス化を明示している印象です。

ただし、変数宣言、作成、初期化を一度に実行する最後の公文では newを使わずにインスタンス化している

設計図：クラス（メソッド・プロパティ）
　　　　　　↓
インスタンス：オブジェクト(メソッド・プロパティ）

#配列の生成と初期値
```java
public class Main {
  public static void main(String[] args) {
    int i;
    //System.out.println("iの値: " + i);　宣言した時点（設計図段階）ではnullなのでエラー

    int[] array = new int[1];
    System.out.println("array[0]の値 : " + array[0]);　
    //インスタンス化した時点で初期値が割り振られるのでエラーにならない

    //System.out.println("array[0]の値 : " + array[1]); 
　　//配列のインデックス[1]は存在しないからエラー
  }
}
```

#Stringオブジェクト
文字列のデータは文字の抜き出しや連結、検索など他のデータ型と比べ多くの機能が必要
他データ型と異なり、変数の宣言では特別なstringクラスをインスタンス化する
→java.lang.string　クラス

```java
 string str = "abcde"; //クラスのインスタンス化を明示しない方法
 string str = new string("abcd"); //クラスのインスタンス化を明示する方法
```
クラスのコンストラクタを使用する時以外は、new キーワードを使わない方がメモリ効率が良い

　stringクラスのメソッド
![スキャン 2021-09-13 10.42.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/13b3b83b-59ad-5410-81b6-22595337404b.jpeg)



#多次元配列
```java
public class Multi {
  public static void main(String[] args) {
     //基本的には普通の配列と一緒
     int[][] array;　　//設計図の作成
     array = new int[3][4];  //設計図から容量3×4の箱を作成(jacaではint型初期値は0）

     //int[][] array = new int[3][4];　←二つを省略してこのようにも書ける

     array[0][0] = 100;　//インデックスを指定して代入
     array[0][3] = 200;  //インデックスを指定して代入

     System.out.println("array[0][0]の値 : " + array[0][0]);
     System.out.println("array[0][3]の値 : " + array[0][3]);
        
     //設計図の作成、配列の作成、値の代入を同時に実行
     int[][] array2 = {
           {10, 20, 30, 40},
           {50, 60, 70, 80},
           {100, 200, 300, 400}
           };
     System.out.println("array2[0][0]の値 : " + array[0][0]);
     System.out.println("array2[0][3]の値 : " + array[0][3]);      
  }
}
```
多次元配列のイメージはX,Y,Zのグラフをイメージすると分かりやすい。

##要素数が不揃いな多次元配列
```java
public class Multi2 {
 public static void main(String[] args) {

　　//array配列のインスタンス作成
　　//数値の入る箱のx軸を3つに設定、Y軸は未設定
    int[][] array = new int[3][];

　　//array配列のインデックス[0]に対し
    array[0] = new int[3]; //X軸[0]にY軸3つの区画を割り当てる
    array[1] = new int[5]; //...5つ
    array[2] = new int[2]; //...2つ
　　//この時点で配列arrayのX,Y区画数が決定  →  インスタンスとして機能する

　　// 上記を一括で実行
    int[][] array2 = {
               {10, 20, 30},
               {50, 60, 70, 80, 90},
               {100, 200}
            };

     System.out.println("array2[0][0]の値 : " + array[0][0]);
     System.out.println("array2[1][4]の値 : " + array[1][4]);
    }
}
```
要素数のふぞろいな多次元配列のインスタンス化はややこしい。
便宜的にX,Yと表現していますが僕の中のイメージです。

####1：配列X軸に対して new を明示し要素数を指定してインスタンス化する
####2：要素数を指定した配列のx軸に対して、それぞれ new を明示し要素数を指定する（Y軸）

ややこしいのは 1でインスタンス化（領域確保）した要素はX軸のみで
2でインスタンスしたX軸要素に対して、1次元配列と同じようにY軸のインスタンス化を行う事

完全に僕のイメージです

##多次元配列の作成　エラーパターン
```java
public class Multi3 {
    public static void main(String[] args) {
      int[][] a1 = new int[2][];        // OK
      //int[][] a2 = new int[][2];      // コンパイルエラー
      //int[] a3 = new int[2]{ };       // コンパイルエラー
      //int[] a4 = new int[2]{10, 20};  // コンパイルエラー
      int[] a5 = new int[]{10, 20};     // OK
      int[] a6 = { };                   // OK
      int[][] a7 = { };                 // OK
      int[][] a8 = new int[][]{ };      // OK
      //var a9 = {10, 20};              // コンパイルエラー
      var a10 = new int[]{10, 20};      // OK
    }
  }
  
```
行数と理由
1.X軸の配列要素のみインスタンス化は可能
2.Y軸の配列要素のみのインスタンス化はできない
3．4：要素数指定と初期化を同時に行えない。
　3.一次元配列の要素数を[2]で指定。{}で初期化を同時に行っている。
　4.一次元配列の要素数を[2]で指定。{10,20}で初期化を同時に行っている。
5.一次元配列の要素数は指定せず{10,20}で初期は可能。
　int[] a5 = {10,20}　と同義
6.同じく要素数を指定せず{}（null）で初期化は可能
7.同じく二次元配列の要素は指定せず{}（null）で初期化は可能（初期化しているのはX軸のみ）
8.　7と同義
9.配列の初期化ではデータ型を明示しないと予測する事ができないため
10.データ型が明示されているためOK

##コマンドライン引数

```java
public class Comand {
    //引数はString[]配列に格納されargsに引き渡される
    public static void main(String[] args) {
      System.out.println(args[0]);
      System.out.println(args[1]);
      System.out.println(args[2]);
      System.out.println(args[1] + args[2]);
    }
  }
```
上記のComandクラスをターミナルで実行する際、一緒に引数を指定する

```   
naito
20
50
2050  ←String型なので足し算されない
```
main()メソッドの引数String[]　argsの使い方がわかった

#第2章感想
配列の宣言、作成、初期化の書き方ルールが複雑なので問題を解いて慣れる必要がある
JavascriptやPHPでは何となくでできていた事もJavaでは厳密にルールに沿って記載しなければいけない。