あらためてJavaを学習する（その1）変数

Java学習の備忘録です。
Javaインストールから簡単なクラスの説明などは「あらためてJavaを学習する(その0)」で解説してます。
[あらためてJavaを学習する(その0)](https://qiita.com/takuyaTT/items/982a2706cf716f34774b)

## 変数(variable)
メモリ領域(記憶装置)に名前(識別子)をつけて値を保存すること。
変数を用いることで、データを一定期間記憶し必要なときに利用することができる

1. メモリの場所に変数名をつける
2. `データ型`を指定して、`値(value)`を代入する
3. 値を呼び出す際は、変数名 → メモリ番地を参照 → 値を取得 の順になる

変数に入れる値のことを`リテラル`と呼ぶ。

### 識別子のルール

* 予約語以外であれば任意で指定可能
* 英数字、アンダースコア(_)、ドルマーク($)が利用可能。
* 数字で始まることはできない

＜重要ポイント＞
**小文字と大文字は区別される**

### データ型
データ型は2種類ある。

* 基本データ型(プリミティブ型)  
変数に直接値を入れる
* 参照型  
参照するメモリの番地(アドレスの値)を保持(文字列や配列など)

#### 基本データ型の一覧

| データ型 | 説明 | サイズ |
| --- | --- | --- |
| byte | 整数( -128 ~ 127 ) | 8bit |
| short | 整数( -32,768 ~ 32,767 ) | 16bit |
| **int** | 整数( -2,147,483,648 ~ 2,147,483,647) | 32bit |
| long | 整数( -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807) | 64bit |
| float | 浮動小数( ±1.40239846 × (10 の－ 45 乗) ~ ±3.40282347 × (10 の 38 乗) | 32bit |
| **double** | 浮動小数( ±4.940655645841246544 × (10 の -324乗) ~ ±1.79769313486231570 × (10 の 308乗 ) | 64bit |
| char | 1文字(Unicode) | 16bit |
| **boolean** | 真偽値(true/false) | 1bit |

太字がよく使うデータ型

### 変数の宣言

```java
// データ型 変数名;
int num;

// 宣言と初期化
// データ型 変数名 = 値;
int num = 1;
```

### ※変数の初期化
変数に対して最初に値を代入すること。
値を代入せず変数宣言を行い、変数を利用しようとするとエラーとなる。

```java
int num;
System.out.println(num); // error: variable num might not have been initialized
```

## 参照型
クラスから生成したインスタンスや配列などは参照型となる。
ざっくり書くと「基本データ型以外のデータ型」は参照型。

参照 = **「値を指し示すもの（メモリのアドレス）」**

参照型には**何も参照していない**ことを示す`null`が代入できる。

### 文字列
データ型は`String`。
文字列は基本データ型ではなく**参照型**。
JavaScriptなどの他の言語では、シングルクォーテーション(`'`)でも代入できるが、Javaの場合はダブルクォーテーション(`"`)のみとなる。

```java
String str1 = "Hello Java";
String str2 = 'Hello Java'; // error: unclosed character literal
```

### 配列
**同じデータ型で複数データをひとまとめにした**もの。
初期化には`new`を指定する。

宣言と初期化が同時であれば、newを用いず`{}`の記述を行い、その中に値をカンマ(`,`)で区切って代入することが可能。
なお、`{}`を使うことで、宣言と代入を分割して記述することもできるが、その際は[ ]の中に要素数の指定はできない。（{ }で指定した要素数で配列の要素が決まるため）

```java
// **** 宣言 ****
// データ型[] 変数名;
// データ型 変数名[];
int[] numbers;

// **** 初期化 ****
// 変数名 = new データ型[データの個数];
numbers = new int[10];

// **** 宣言と初期化 ****
String[] names = {"Java", "PHP", "COBOL"};

// **** 分割 ****
int[] nums;
nums = new int[]{1, 50, 200};
```

各値は`インデックス`を指定することで取得することができる。先頭は**0**となる。
なお、インデックスを指定しない場合はその配列の参照値が取得できる。

```java
System.out.println(names[0]); // Java
System.out.println(numbers); // [I@36baf30c
```

### 初期化のデフォルト値
`new`で要素分の配列を確保した時点で、デフォルト初期値が設定される。

| データ型 | 初期値 |
| --- | --- |
| boolean[ ] | false
|int[ ], long[ ], float[ ], double[ ], char[ ], byte[ ] | 0 |
| 上記以外(String型など) | null | 

### 多次元配列
配列の中に配列を指定できる。

```java
String[][] progs = new String[2][2];
        progs[0][0] = "Java";
        progs[0][1] = "PHP";
        progs[1][0] = "Oracle";
        progs[1][1] = "The PHP Group";
        
        System.out.println(progs[0][0]); // Java
        System.out.println(progs[1][0]); // Oracle
```

## 変数のスコープ
スコープ = **変数の有効範囲**
ブロック`{ }` 内で宣言した変数は、そのブロック内だけで有効であり外からは参照できない。

```java:Main.java
public class Main {
    int a = 1;
    
    public static void main(String[] args) {
        // 変数bをここで宣言する
        int b = 10;
        Main mainClass = new Main();
        mainClass.printNum();
    }
    
    void printNum(){
        int c = 100;
        System.out.println(a);
        // bは宣言されていないためエラーが起きる
        System.out.println(b); // error: cannot find symbol
        System.out.println(c);
    }
}
```


## 演算子
演算子自体を`オペレータ`と呼び、値のことを`オペランド`と呼ぶ。
値と演算子を組み合わせた計算の単位を`式`と呼ぶ。

### 主な演算子一覧
int a = 1;
int b = 2;

| 演算子 | 説明 | 記述例 | 結果 | 備考 |
| :-: | --- | :-: | :-: | --- |
| + | 加算 | 10 + 1| 11 |
| - | 減算 | 10 - 1 | 9 |
| * | 乗算 | 10 * 10 | 100 | 
| / | 除算 | 10 / 2 | 5 |
| % | 剰余 | 10 % 3 | 1 |
| += | 加算(a = a + 1) | a += 1  | 2 |
| ++ | 加算(a = a + 1) | a++ または ++a  | 2 | インクリメント(サンプルコード参照) |
| -= | 減算(b = b -1) | b -= 1 | 1 |
| -- | 減算(b = b -1) | b-- または --b | 1 | デクリメント(サンプルコード参照) |
| *= | 乗算(b = b * 2) | b *= 2 | 4 |
| /= | 除算(b = b / 2) | b /= 2 | 1 |
| %= | 剰余(b = b % 2) | b %= 2 | 0 |
| > | 比較(aがbより大きい) | a > b | false | |
| < | 比較(aがbより小さい) | a < b | true | |
| >= | 比較(aがb以上) | a >= b | false | |
| <= | 比較(aがb以下) | a <= b | true | |
| == | 比較(aがbと等しい) | a == b | false | 文字列の値比較の場合は**String#equalsメソッド**を利用(サンプルコード参照) |  
| != | 比較(aとbが異なる) | a != b | true | |
| & | 論理積(AND) | a > b & a != b | false | 左辺がfalseでも右辺も評価を行う |
| && | 論理積(AND) | a > b && a != b | false | 左辺がfalseの時点で評価を終える(右辺の評価はしない) |
| &#124; | 論理積(OR) | a > b &#124; a != b | true | 左辺がtrueでも評価を行う |
| &#124;&#124; | 論理積(OR) | a > b &#124;&#124; a != b | true | 左辺がtrueの時点で評価を終える(右辺の評価はしない) |

#### サンプルコード

```java:Sample1.java
public class Sample1 {
    public static void main(String[] args) {
        // **** インクリメント・デクリメント ****
        int a = 1;
        int b = 2;

        System.out.println(a++); // 1
        // System.out.println(a); 
        // a = a + 1;
        System.out.println(++a); // 3
        // a = a + 1;
        // System.out.println(a);
        
        System.out.println(a++ + --a + b--); // 8
        System.out.println("a : " + a + " , b : " + b); // a : 3 , b : 1
        
        
        // **** 文字列の値比較 ****
        String str1 = "Hello";
        // インスタンス生成
        String str2 =  new String("Hello");

        System.out.println(str1 == str2); // false
        System.out.println(str1.equals("Hello")); // true
        
        
        // **** ANDとOR ****
        int x = 10;
        if(false && ++x == 11){ // 右辺は評価されない
            System.out.println(x);
        }
        if(false & ++x == 11){ // 右辺は評価される
            System.out.println(x); 
        }
        
        System.out.println(x); // 11
    }
}
```

#### 文字列と数値の連結
数値側は自動的に文字列に変換されて結合される
括弧() で括ることで、演算結果をうまく連結することができる

```java:Sample2.java
public class Sample2 {
    public static void main(String[] args) {
       int num = 1;
       String str = "1";
       System.out.println(str + num); // 11
       
       System.out.println(str + (num + 3)); // 14
       System.out.println(str + num + 3); // 113
    }
}
```


## キャスト(明示的型変換)
大きい型から小さい型への変換の場合は、明示的に宣言(`キャスト`)しないとエラーとなる。

型によって保持できる値の範囲があるため、容量越えの値をキャストした場合は桁落ちなどで想定外の結果になる可能性があるので注意。

小数から整数へのキャストの場合は、小数点以下は切り捨てられる。

＜キャストが不要な場合の条件＞
* 小さい型から大きい型への変換
* 整数から小数への変換


```java
int intNum = 10;

// 小　→ 大
long longNum = intNum;

// 大　→ 小
// データ型 変数名 = (データ型)変数名;
byte byteNum = (byte)intNum;

System.out.println(longNum); // 10
System.out.println(byteNum); // 10

// 小数　→ 整数
double doubleNum = 3.1416;
intNum = (int)doubleNum;
System.out.println(intNum); // 3
```

## 最後に
変数についてザックリと学習してみました。
次回は基本構文の学習をザッと行いたいと思います！

## 参考文献
この記事は以下の情報を参考にして執筆しました。
【サイト】
・Wikipedia：[変数(プログラミング)](https://ja.wikipedia.org/wiki/変数_(プログラミング))
・苦しんで覚えるC言語：[数値を記録する](https://9cguide.appspot.com/05-01.html)
【書籍】
・「基礎からのJava」SB Creative出版：[基礎からのJava　改訂版](https://www.sbcr.jp/product/4797359275/)