Java入門シリーズ(変数と型)

## はじめに

こんにちは。
この記事は「これからJavaを始める方」や「久々にJavaにやる方」向けに変数と型についてのまとめ記事です。

変数とは何かといったプログラミング自体についての説明は行わないので、プログラミング初心者の方には向いてない記事かもしれません。

Java入門シリーズとして下記の記事を準備中です。

- 変数と型　←いまここ
- [型変換](https://qiita.com/aoyaman/items/cbefb07c6fffcbadf2ef)
- 変数のスコープ（準備中）
- 文字列の操作（準備中）
- 配列の操作（準備中）
- 演算子（準備中）
- 条件分岐（準備中）
- 繰り返し処理（準備中）
- クラスについて（準備中）
- 抽象クラス（準備中）
- インターフェース（準備中）
- カプセル化（準備中）
- モジュールについて（準備中）

# 型について

JDK10から型推論の概念が導入されてますが
Javaの基本は静的型付言語だと思いますので
型について説明します。

型は大きく分けて、
基本型(プリミティブ型)と参照型(クラス型)の２種類あります。

## 基本型(プリミティブ型)
整数、少数点数、boolean、文字の４種類あります。
c言語と違ってunsigned(マイナスなし)はありません。

#### 整数型

サイズによって形が４種類あります。

| 型 | サイズ | 値の範囲 |
|:-:|:-:|:-:|
|byte| 8ビット|-128〜127|
|short|16ビット|-32768～32767|
|int|32ビット|-2147483648～2147483647|
|long|64ビット|-9223372036854775808～9223372036854775807|

私の印象としては、

基本的にはintを使って、サイズが足りなければlongを使う。
byteはバイナリデータをファイルなどから読み込んだ際の配列の型として使う。
shortは全然使わない。

となっています。
（ベストプラクティスのようなものをご存知の方がいれば教えてください）

値の範囲を超えると値が反転します。

```java
int test = 2147483647;
System.out.println(test); // -> 2147483647
test++;
System.out.println(test); // -> -2147483648
test--;
System.out.println(test); // -> 2147483647
```

#### 小数点数型

こちらもサイズによって２種類あります。

| 型 | サイズ | 値の範囲 |
|:-:|:-:|:-:|
|float| 32ビット|±3.40282347E+38 ~ ±1.40239846E-45|
|double|64ビット|±1.79769313486231570E+308 ~ ±4.94065645841246544E-324|

割り算など小数点以下の値を扱う場合に使用します。
整数型では割り算をした場合など小数点以下は切り捨てられます。

```java
int a = 5, b = 3, c = 0;
c = a / b;
System.out.println(c);
// -> 「1」と出力される。
```

```java
float a = 5, b = 3, c = 0;
c = a / b;
System.out.println(c);
// -> 「1.6666666」と出力される。
```

```java
double a = 5, b = 3, c = 0;
c = a / b;
System.out.println(c);
// -> 「1.6666666666666667」と出力される。
```

#### boolean型

true か false のみが入る型です。

```java
boolean a = true, b = false;
boolean c = a == b;
System.out.println(c); // -> 「false」と出力される
```

#### char型

文字を扱う型です。文字列として扱う際には配列を利用します。

```java
char  a = 'a', b = 'b';
System.out.println(a); // -> 「a」と出力される
System.out.println(b); // -> 「b」と出力される
char[] str = {'a', 'b', 'c'};
System.out.println(str);  // -> 「abc」と出力される
```




## 参照型(クラス型)

クラスのインスタンス(実体)を格納する変数の型を参照型(クラス型)と呼びます。

参照型と呼ぶのは、
値そのものを保持するのではなく、値が置いてある場所を保持するからです。

ですので、参照型の変数をコピーするということは、
値そのものをコピーするのではなく、
値が置いてある場所の情報をコピーするという意味になるのでご注意ください。

下記のプログラムは参照型の変数をコピーした後に、
コピー先の変数を使って値を書き換えるというものです。

```java
public class Test {
	public int value = 0;
}
public class Main {
	public static void main(String[] args) {
		Test x = new Test();
		x.value = 5;
		Test y = new Test();
		y.value = 5;
		System.out.println(x.value); // -> 「5」と出力
		System.out.println(y.value); // -> 「5」と出力

		x = y;
		x.value = 10;
		System.out.println(x.value); // -> 「10」と出力
		System.out.println(y.value); // -> 「10」と出力
	}
}
```

x = y;
にて、変数xにコピーされたのは変数yに入ってた「値が置いてある場所の情報」なので、
変数xと変数yには同じ場所の情報が入ってます。
よって、
変数xを使って値を書き換えると、変数yの指し示す値も変更されてることになります。

ここで言う「場所」というのは、メモリ空間上の場所のことになります。
C言語のポインタと似たようなイメージですね（厳密には別物ですが)

### ラッパークラス

Javaには標準で様々なクラスが用意されていますが、
上述の基本型(プリミティブ型)をラッパーしたラッパークラスが存在します。

IntegerクラスやStringクラスなどです。

Integerクラスは数値を扱うクラスで
int型と同じように代入や四則演算、比較演算しなどを使うことが出来ます。

```java
class Main {
  public static void main(String[] args) {
    int a = 5;
    Integer b = 3;
    int c = a * b;
    int d = b;
    System.out.println(c);  // -> 「15」と出力される
    System.out.println(a == b); // -> 「false」と出力される
    System.out.println(d); // -> 「3」と出力される
  }
}
```

Stringクラスは文字列を扱うクラスで
文字の結合や比較など文字列に対する様々な機能が実装されています。

```java

class Main {
  public static void main(String[] args) {
    String a = "a";
    String b = "b";
    String c = a + b;
    String d = b;
    System.out.println(c);           // -> 「ab」と出力される
    System.out.println(c.length());  // -> 「2」と出力される
    System.out.println(a.equals(b)); // -> 「false」と出力される
    System.out.println(b.equals(d)); // -> 「true」と出力される
  }
}
```

※このラッパークラスは基本型(プリミティブ型)と同じように振る舞えるよう実装されているため、代入時に参照型のように「値が保存されている場所」が代入されず、値そのものが代入されますので、ご注意ください。

```java
class Main {
  public static void main(String[] args) {
    Integer i = 5;
    Integer j = 6;
    System.out.println(i);  // -> 「５」と出力される
    System.out.println(j);  // -> 「6」と出力される
    j = i;
    j = 7;
    System.out.println(i);  // -> 「５」と出力される
    System.out.println(j);  // -> 「7」と出力される

    String a = "a";
    String b = "b";
    System.out.println(a);  // -> 「a」と出力される
    System.out.println(b);  // -> 「b」と出力される
    b = a;
    b = "B";
    System.out.println(a);  // -> 「a」と出力される
    System.out.println(b);  // -> 「B」と出力される
  }
}
```

## 変数の宣言

Javaでは「型名 変数名」という形で宣言します。

型名と変数名の間に半角スペースやタブ文字で間をあけます。

また、同じ型の変数であればカンマ区切りで宣言もできます。

```java
int a;
int b;
int c, d, e;
```

配列については別途「配列の操作」という記事を書く予定です。

## 変数の初期化

Javaでは「型名 変数名 = 値」の形で変数を初期化できます。

```java
int a = 5;
int b = 10;
int c = 5, d, e;
```

## 変数の宣言場所

プログラミング言語によっては、
変数宣言は処理ブロックの先頭のみという制約がある場合がありますが、
Javaではどこでも宣言できます。

```java
class Main {
  public static void main(String[] args) {
    int n = 5;
    for (int i = 0; i < 5; i++) {
      System.out.println(i);
    }

    String msg = "";
    for (int i = 0; i < 5; i++) {
      msg += i;
    }
    System.out.println(msg);
  }
}
```

## 変数の名前

### 使える文字
アルファベット、数字、アンダーバー、$
となります。

### 大文字小文字の区別がある
大文字と小文字は別の文字として扱われれます。

```java
class Main {
  public static void main(String[] args) {
    String name = "name";
    String Name = "Name";
    System.out.println(name + Name); // -> 「nameName」と出力される
  }
}
```

### 数字は先頭文字に使えない
先頭にはアルファベットをつけましょう。
![変数名の先頭に数字はダメ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150699/b04a8e63-68a7-21a2-78dd-f96813b837b4.png)

### 予約語や用意された定数は使用できない

予約後は if や class などJavaのプログラムを書く際のキーワード達です。
[Oracleのドキュメント](https://docs.oracle.com/javase/specs/jls/se11/html/jls-3.html#jls-3.9)を参照ください。

用意された定数とは、null, true, false です。これらも変数名としては使用できません。

## おわりに

Javaの変数と型について、いかがでしたでしょうか？

少し前まではrubyやjavascriptなど型を書かない言語が
型なしでさくさく書けるというメリットアピールが大きかったと思いますが、

最近(2020/05)では、typescriptが出てきたりと型についての必要性が見直されてきてるのかと思います。

おわり。