Java概念入門

# Java入門

## はじめに

当記事は[TECHSCORE](http://www.techscore.com/)の[Java入門](http://www.techscore.com/tech/Java/JavaIntro/index/)を私的勉強の為に読みながら内容を端的にまとめたものです。
内容的にはJavaにおける下記キーワード等の概念を理解するのに役立つと思います。
ロジックに関わる具体的な構文等についてはほとんど触れていません。
記事内の記述に誤り等あればご指摘いただければ幸いです。

- 変数
- クラス
- インスタンス
- 継承
- オーバーロード
- オーバーライド
- アクセス修飾子

## Hello World!

```java
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
```

- Javaのすべてのプログラムは**クラス(Class Object)**で構成されている。 (Hello)
- Public(後述)なクラスのクラス名はそのままファイル名になる必要がある。（Hello.java)
- クラスは**インスタンス(Instance Object)**のひな形であり、クラスを基にインスタンスが作成される。
- クラスから作成されたObjectを組み合わせてプログラムを動かすのがJavaのオブジェクト指向。

## 変数(Variables)

```java
public class VarSample {
    public static void main(String[] args) {
        int a = 5;
        System.out.println(a);
    }
}
```

- Javaで**変数**を利用する際は**型**を指定し変数のを宣言する。
- 型にはプリミティブ型(基本データ型)とクラスを用いる参照型が存在する。
- 値の代入は後で行ってもよい。

プリミティブ型(基本データ型)一覧

| 種類 | 型 | 値 | bit数 |
|---|---|---|---|
| boolean | boolean | true/false | 1bit |
| 整数型 | byte | -128～128 | 8bit整数 |
| 整数型 | short | -32768～32767 | 16bit整数 |
| 整数型 | int | -2147483648〜2147483647 | 32bit整数 |
| 整数型 | long | -9223372036854775808〜9223372036854775807 | 64bit整数 |
| 整数型 | char | 1文字 | 16bit整数 |
| 浮動小数点型 | float | 単精度浮動小数点数 | 32bit実数 | 
| 浮動小数点型 | double | 倍精度浮動小数点数 | 64bit実数 | 

- 文字列はプリミティブ型ではなくjava.lang.Stringというクラスのインスタンス(参照型)として扱う。
- 数値型間の変換は可能でこれを**キャスト**と呼ぶ。精度は変換先に準拠する。

```java
float a = 3.14;
int b = (int)a; // b = 3
```

## クラス

### クラスとインスタンス

```java
public class Human {
 
    private String name = null;
    private int age = -1;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age){
        this.age = age;
    }
 
    public String toString(){
        return "名前は" + name + "さんです。年は" + age + "歳です。";
    }
}
```

- 上記クラスのHumanは特定個人を表現していない。あくまでもクラスは雛形でしかない。
- クラスから個々のインスタンスを生成し、それに情報を持たせることで特定個人を作る。
- クラスの修飾子は`public`, `final`, `abstract`などがある。

## フィールド

```java
public class Human {
 
    private String name = null;
    private int age = -1;
    
    private static int NUM_EYE = 2;
}
```

- フィールドは**クラス変数**と**インスタンス変数**が存在する。
- クラス変数はクラスに属する変数で、アプリケーション全体で同じ値を参照する。
- インスタンス変数はインスタンスごとに持つ変数で、インスタンスごとの異なる値を参照する。
- 修飾子に`static`を加えるとクラス変数になる。
- 修飾子には`public`, `protected`, `private`, `static`などがある。（後述）

## メソッド

```java
public class Human {
 
    private String name = null;
    private int age = -1;
 
   
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
}
```

- **メソッド**はクラスとインスタンスの持つ機能や操作。
- 値を受け取り、受け取った値で処理を行い、処理の結果の値（**戻り値**）を返す。
- `void`(戻り値なし)以外を指定したメソッドは必ず指定した型の戻り値を返す必要がある。
- `this`はインスタンスを指し、引数の値と区別して使う。

### オーバーローディング

```java
public String getName() {
    メソッド内処理 A
}
 
public String getName(int a, boolean b) {
    メソッド内処理 B
}
```

- 同じ名前で呼び出しても引数の違いによって違うものが呼ばれるようにメソッドを定義すること**をオーバーローディング**と呼ぶ。
- `getName()`としたら処理A、`getName(10, true)`としたら処理Bが実行される。
- 同一シグネチャ(メソッド名、引数の型、引数の数、引数の並び順)を持つメソッドは定義できない。

## 継承

```java
public class Student extends Human {
 
    private String school = null;
 
    public String getSchool() {
        return school;
    }
 
    public void setSchool(String school) {
        this.school = school;
    }
 
    public String toString() {
        return "名前は" + name + "さんです。年は" + age + "歳です。学校は" + school + "です。";
    }
 
}
```

- `extends Human`は`Student`クラスが`Human`クラスを**継承**していることを表す。
- `Human`のメンバ(フィールドとメソッド)は全て`Student`でも継承され定義されているので、利用できる。
- そのため、サブクラス(継承先のクラス)はスーパークラス(継承元のクラス)のインスタンスとして扱うことができる。

### アクセス修飾子

| 修飾子 | 意味 |
|---|---|
| public | どのクラスからもアクセス可能 |
| protected | サブクラスおよび同一パッケージのクラスからのみアクセス可能 |
| 修飾子なし(デフォルトアクセス) | 同一パッケージのクラスからのみアクセス可能 |
| private | 同一クラスからのみアクセス可能 |

- アクセス修飾子を適切に設定することでアクセス制御を実現し、意図しない操作や内部の処理の隠ぺい(**カプセル化**)ができる。
- 継承にある`Student`クラスが`Human`から継承した`toString`は`private`なフィールド`name`と`age`にアクセスしようとしている為、コンパイルエラーが起きる。
- 対応として`Human`クラスのフィールドを`private`から`public`や`private`にすることでコンパイルエラーは解除できるがアクセス制御の目的から外れてしまう。
- 正しい対応としては`public`で作った`Human`クラスのgetterメソッドを介して下記のように実装することで、アクセス制御を保ったまま意図通りの挙動になる。

```java
public String toString() {
    return "名前は" + getName() + "さんです。年は" + getAge() + "歳です。学校は" + school + "です。";
}
```

#### 修飾子`final`

- クラスに`final`がつくと継承が不可能になる。
- メソッドに`final`がつくとオーバーライドが不可能になる。
- フィールドに`final`がつくとその値が定数になり変更が不可能になる。

### オーバーライド

- `toString()`メソッドは`Human`クラスで定義されたものが`Student`クラスで**オーバーライド**(上乗せ)し再定義されている。
- オーバーライドは下記の規定がある。
  - オーバーライドする側とされる側の戻り値の型、メソッド名、引数の型、引数の数、引数の並び順が同じであること。
  - アクセスレベルが元のメソッドよりも緩くなっていないこと。
  - オーバーライド元のメソッドが投げる例外以外の例外を、オーバーライド先のメソッドが投げていないこと。（ただし、元のメソッドの投げる例外を限定したものであればよい。）
  - オーバーライド元のメソッドに修飾子 final がついていないこと。
  - スーパークラスで abstract として定義されているメソッドはオーバーライドするか、サブクラス自身を abstract にしなければならない。
- オーバーライドしていることを明示的にするため、`@Override`というアノテーション(注釈)をつけることが推奨されている。
- `Student`クラスから親クラスである`Human`クラスで定義した`toString()`を呼ぶこともできる。その場合は`super.toString()`と記述する。(ただし`private`メソッドの場合できない。)

```java
public class Student extends Human {
 
    private String school = null;
 
    public String getSchool() {
        return school;
    }
 
    public void setSchool(String school) {
        this.school = school;
    }
 
    @Override
    public String toString() {
        return "名前は" + getName() + "さんです。年は" + getAge() + "歳です。学校は" + school + "です。";
    }
 
}
```

## インスタンスの生成

### コンストラクタ

- **コンストラクタ**は全てのクラスが持っている特殊なメソッドであり、インスタンスの初期化処理を実行する。
- インスタンス生成時に必ずコンストラクタが実行される。
- コンストラクタ名はクラス名と同一で、返り値は指定できない（voidも記述しない）。
- コンストラクタはメンバではないため、継承、オーバーライドもされない。
- クラス内で明示的に宣言しなくてもコンパイラが暗黙的に提供する。明示的な宣言ももちろん可能。
- コンストラクタを呼び出すのは基本的にインスタンス生成時、他コンストラクタからの呼び出し時となる。

### インスタンスの生成

```java
public class CSVReader {
 
    public static void main(String[] args) {
        Human taro = new Human();
    }
 
}
```

- `new`演算子とコンストラクタ`Human()`を用いて`Human`のインスタンスである`taro`を生成している。

## 入出力とパッケージ

### 入出力

- Javaのデータ入出力は**ストリーム**(Stream)という概念で行われる。
- 入出力の流れは必ず「ストリームを開く⇒データがなくなるまで書込/読込を行う⇒ストリームを閉じる」となる。

```java
import java.io.FileReader;
import java.io.BufferedReader;

public class CSVReader {

    public static void main(String[] args) {
        FileReader reader = new FileReader("member.csv");
        BufferedReader br = new BufferedReader(reader);

        // ここに処理を記述

        br.close();
    }
}
```

外部ファイル：member.csv

```
MichaelDesanta,48
TrevorPhilips,48
FranklinClinton,28
```

- `import`文により他クラスを自クラス内で使えるようにできる。
- `import`なしだと下記のような記述になる。

```java
java.io.FileReader reader = new java.io.FileReader("member.csv");
```

- `FileReader`型の変数`reader`で`member.csv`を読み込んだ`FileReader`のインスタンスを代入している。
- `BufferReader`は読込をバッファして高速化する為に利用している。（FileReaderは逐次アクセスの為遅い）

### パッケージ

- パッケージを利用してクラスファイルの管理を行い以下3つのメリットを享受できる。
  - クラスファイル分類 - パッケージによる分類で目的のクラスがどこにあるか解りやすくなる。
  - クラスファイル名の衝突防止 - 別パッケージであれば同クラス名が存在できる。(ただし利用時は片方を完全限定名にする必要がある)
  - アクセス制御 - パッケージを基準にアクセス制御ができる。
- パッケージを指定せずともクラスファイルは作成できるが、扱いづらいため非推奨。
- `String`を含む`java.lang`パッケージのみ例外的に`import`の省略ができる。