関数型言語しかしらない学生がJava上でのオブジェクト指向・クラス概念などを勉強した記録

# オブジェクト・インスタンス・クラスとは？
## オブジェクト(インスタンス)とは？
複数の変数・メソッド（後述）を一つのまとまりとして扱うことができるようにまとめたもの。
これの中にある変数のことを**メンバ変数**と呼び、中にあるメソッドを**メンバメソッド**と呼ぶ。


## クラスとは？
オブジェクト(インスタンス)の設計図。
あらかじめ宣言しておき（設計図を作っておくような感覚）、使用する場面で設計図をもとに実際に使うことができるもの（**オブジェクト**・**インスタンス**）を作る（**インスタンス化**）

### クラスの宣言の仕方
```java 
class TestClass {
    int data1;
    int data2;
}
```
+ *class [クラス名] {    //クラスに含むメンバ すべて  }*

### 宣言したクラスを使うには？（クラスのインスタンス化）
例）main (String args[]) {    // のなかで

```java 
TestClass t = new TestClass();
```

+ *[クラス名（型宣言）]  [オブジェクト名（代入したいオブジェクトの名前）] = new [クラス名]（）;*

※最後のクラス名の後の**"()"の中に変数や初期値を与える**こともでき、これを使うことでオブジェクトごとに別の初期値を与えることもできる。（後述）

### インスタンス化したオブジェクトのメンバ変数を使うには？

```java 
t.data1 = 100;
//TestClassをインスタンス化した,tの中のdata1を呼び出している
System.out.println(t.data1);    // =>100
```

# クラスの継承とは？

すでに作成されたクラスをもとに、拡張版（**変数の追加や変数の上書き**を行われたもの）のクラスを作るための機能のこと。

## どうやって継承するの？
```java 
class TestClassPlus extends TestClass {
    double data3;       //メンバ変数の追加
    long     data4;
    data1 = 2;            //値の上書き
}
``` 
+ *class [継承先のクラス名]* 　 **extends** 　*[継承元のクラス名] {    //継承後クラスに* **追加したいもの・上書きしたいもの** *}*

※extendsの意味…延長する。→クラスに必要なメモリ容量の付け足しと思えば理解しやすい。

## 親クラスのオブジェクトと子クラスのオブジェクトの関係性

（あまり使うことはないが、）子クラスのオブジェクトを親クラスのオブジェクトに代入した場合の挙動は、親クラスに存在するメンバなら呼び出すことはできるが、**継承時に追加・変更されたオブジェクトは参照・使用することはできない**。
→親クラスで確保されたサイズのメモリしか保有しないため。

例）上記のTestClassとTestClassPlusを使用する

```java 
TestClass t;
TestClassPlus tp = new TestClassPlus();

tp.data1 = 123;
tp.data2 = 456;
tp.data3 = 789.0;

t = tp;

System.out.println(t.data1);        //=>123
System.out.println(t.data2);        //=>456
System.out.println(t.data3);        //=>コンパイルエラーになる（実行不可）

```


# メソッド・コンストラクタとは？

## メソッドとは？

クラスの中に定義する関数のこと。クラス内で定義されている変数に対する処理や、そのクラスに関する処理をまとめて記述する。一度作ってしまえば、面倒な処理を肩代わりしてくれるものである。

例）宣言の仕方(TestClass内で)

```java 
int data1 = 0;
int data2 = 1;
void show(){
    System.out.println(data1);
    System.out.println(data2);
}
```

例）呼び出し方

```java 
t1.show(); //o(改行)1
```

## コンストラクタとは？

メソッドのうち、クラスがインスタンス化されたときに必ず実行されるメソッド。多くの場合ここでメンバ変数の初期化を行う。
また、インスタンス化の際に使う、``new [クラス名]();``の括弧内に引数を与えると、コンストラクタ内で使うことができる。

## メソッドの定義とコンストラクタの定義の例
例）上記のTestClassにメソッドとコンストラクタを追加する

```java 
class TestClass {
    int data1 = 0;
    int data2 = 1;
    
    //コンストラクタ
    TestClass(int input1, int input2){
        data1 = input1;        //=>引数input1に指定された値をdata1に代入している
        data2 = input2;        //    →インスタンス化の時に引数で初期値を指定すればそのたびに自動で代入してくれる
    }
    
    //メンバ変数を表示するメソッド
    void printData() {
        System.out.println(data1);        //=>同じクラスの中なので、"t.data1"のようなオブジェクト内の変数を指定する
        System.out.println(data2);        //    形ではなく、単純に"data1"のようにメンバ変数名だけでよい。
    }

```

**※コンストラクタはクラス名と同じ名前のメソッドを定義する。**

### 定義されたクラスを使うには

例）上記のメソッドとコンストラクタが追加されたTestClassを使用する

```java 
TestClass t = new TestClass(100, 200);        //コンストラクタを使った初期化が起きている

t.printData();    //=>100（改行）200
//↑ではSystem.out.println(data1)とSystem.out.println(data2)が実行されている
```

## オーバーライドって？

親クラスを子クラスに継承する際に**親クラスのメンバメソッドを上書き**すること。

# パッケージとは？

**複数のクラスをまとめる**ことで、関連するクラスを分類しやすくする考え方。
名前空間にもなり、別のパッケージであれば、同じクラス名をつけても衝突が起きない。
また、別ファイルから読み込む際も、パッケージ単位でまとめて読み込むことができ、便利である。

例）TestClassとTestClassPlusを一つの**testパッケージ**にまとめる

```java 
package test.testClass;

//testClassの定義
```

```java 
package test.TestClassPlus;

//TestClassPlusの定義
```

例）二つを別のファイルにまとめて読み込む時

```java 
import test.*;        //testパッケージ以下にあるすべてのクラスを読み込む
```

***

# アクセス制御（private・public・protected・指定なし）

メソッド・変数にアクセス（読み書き）できる対象を制限すること。

## なぜ制限する必要があるのか？

誰でもどこからでも変数・メソッドにアクセスが可能であると、*変数の中身を***意図せず***書き換えたり、予期しないタイミングでメソッドを実行させる*ことができたりしてしまい、**思わぬ挙動が現れる可能性を高めて**しまう。
→これを防ぐために、**アクセスの制限をかけて想定通りの挙動になるように管理**する必要がある。

## publicとは？

**どこから・誰でもアクセスできる**メンバ。これはどのクラスでも、どのパッケージからでもアクセスできる状態である。
多くの場合、**メソッドをpublic指定してメソッド内で引数などを検査してからprivate要素にアクセスさせる、門番**のような役割に使われる。

## protectedとは？

**同じパッケージ・子クラスからのみアクセスできる**メンバ。継承されるクラスで指定される。

## 指定なしのアクセス権限とは？

**同じパッケージからのみアクセスできる**メンバ。publicにはならないので注意。

## privateとは？

**同じクラス・同じクラスから作られたオブジェクトからのみアクセスできる**メンバ。もっとも強いアクセス制限で、アクセス権限がないものがアクセスしようとすると、コンパイル時にエラーを出力する。
多くの場合、メンバ変数は簡単に変更されてはならないので、private指定されている。

### private指定された変数にアクセスするメソッド（Getter・Setter）

private指定された変数にアクセスする門番のようなメソッドは特にGetter・Setterと呼ばれる。
多くのJavaライブラリではこれを自動生成する機能もついている。

#### Getter
変数を表示する・他のメソッド内で使用する場合に**読みだす**ために使われるメソッド。

#### Setter
変数の内容を変更する・他のメソッドの結果を代入する場合に**書き込む**ために使われるメソッド。基本的にここに代入値の検査（バリデーションをかける）を記述する。

***

# Javaの中の変数の型
## プリミティブ型（基本データ型）
メモリの中に書き込まれた情報のことを指す。数値を扱うデータ型では基本的にこれを使用する。これの初期化されていない値は**基本的に0**であって、NULL判定・代入はできない。

|  型名 | 初期値 | 種別 |
|:----:|:------:|:----:|
| byte | 0 | 1バイト整数型 |
| short| 0 | 2バイト整数型 |
| int  | 0 | 4バイト整数型 |
| long | 0 | 8バイト整数型 |
| float| 0.0| 4バイト実数型 |
| double| 0.0| 8バイト実数型|
| boolean| false | 真偽型 |
| char  | 文字コードの"￥u0000"  | 2バイト文字型  |

## 参照型
メモリのアドレス情報のことを指す。クラス・文字列を扱うデータ型ではこれを使用する

### 参照型の代入
同じクラスからインスタンス化された複数のオブジェクトを使って、代入を行うとどのような挙動をするか
例）上記のTestClass が宣言されている。

```java 
TestClass t1 = new TestClass();
TestClass t2 = new TestClass();

t1.data1 = 123;
t2.data1 = 456;

t2 = t1;

System.out.println(t2.data1);    // =>123
System.out.println(t2.data2);    // =>456
```

これは、Javaのクラスが参照型であり、メモリのアドレスを保持しているため、代入を行うことで**アドレスが上書き**される。
アドレスが上書きされることによって、オブジェクト内すべてのデータが書き換えられたように見える。

# Javaにおける配列とオブジェクト

Javaの配列の宣言は二通り存在する。

```java 
//Java正式な宣言
int[] array;

//C/C++風の宣言
int array[];
```

空配列の宣言には**new**演算子を使用する

```java 
int[] array = new int[5];
```
*[型名] [ ]　 [配列名] = new 　[型名][要素数]*

初期値が決まっている場合はC言語の配列宣言のように初期化を同時に行うことができる

```java 
int[] array = {1, 2, 3, 4, 5};        //=>5つの要素が宣言される
```
*[型名][ ]　[配列名] = {初期値}*

## オブジェクトの配列

インスタンス化されたオブジェクトを**配列の中に代入**することも可能である。

例）「メソッドの定義とコンストラクタの定義の例」のTestClass を使用する

```java
TestClass[] TestClassArr = new TestClass[3];    //TestClassの配列の宣言

TestClassArr[0] = new TestClass(100, 200);    //TestClass一つ一つのインスタンス化
TestClassArr[1] = new TestClass(300, 400);    
TestClassArr[2] = new TestClass(500, 600);

System.out.println(TestClassArr[0].data1);    //=>100
System.out.println(TestClassArr[1].data2);    //=>400

```
オブジェクトを代入する配列の宣言→配列一つ一つにオブジェクトを作成していく
※配列内へのインスタンス化を繰り返し文でおこなうことが多い

## Java内のString型の実装

Javaでも文字列をchar型の配列として保持し、そこに様々なメソッドを追加しているので下記のような記述も可能である。

```java 
System.out.println("TESTMOJI".length);    //=>8
```

***

# thisとsuper
## thisとは？
クラス内でその**クラスのオブジェクトを使う場合**に使用する特別な変数。
例）TestClass内で別のメソッドからprintDataメソッドを呼び出す場合

```java 
this.printData();
```
**※Javaではthisの指定をしない場合、暗黙でthis指定（インスタンスのメンバ指定）となる**

## superとは？
継承したクラスの親クラスのメンバを指定するときに使える。子クラスで**オーバーライドしたメソッドの元のメソッドを呼び出すとき**などに使うことができる。

```java 
System.out.println(super.data1);        //=>オーバーライドする前の"0"が表示される
```
# finalとstatic
## finalとは？
クラスにつけた場合、**継承できなくなる**修飾子。
変数につけた場合、**変更できなくなる（定数にする）**修飾子。

```java 
final data5 = 100;
```

## staticとは？
メソッドにつけた場合、**インスタンス化なしで使うことができるようにする**修飾子。
変数につけた場合、**クラス（クラスオブジェクト）に変数を持たせることができる（インスタンス共通の変数を作ることができる）**修飾子

```java
class TestClass{
    static data1 = 0;
}

System.out.println(TestClass.data1);    //TestClassの中に存在するdata1変数
```
static指定することで、**すべてのインスタンスで共有するメンバ**を一箇所に定義することができる。
→メモリ領域を削減することができる
※インスタンス内からstaticメソッドを変更することができるため、注意が必要である。

***

# 例外処理とは？
コンパイル時に発見できる文法エラー以外の**実行中のエラー（例外）**を検知し、対処するための処理。**try句とcatch句**を使う

## tryとは？
try句の中に処理を記述することで、実行中のエラーを例外として検知することができる。

```java 
BufferedReader br = new BufferdReader(InputStreamReader(System.in));
try{
        int inputAns = Integer.parseInt(br.readLine());    //キーボードからの数値の読み込み
        int ans = 10 / inputAns;    //これでは、10÷0というプログラミングの禁忌（結果が無限大になってしまうため）が起きる可能性がある。
}
//以降のcatch文などは次項から解説するので省略。（catch・finalyがない場合はSyntaxエラーとなるので注意）        
```

※これで実行時のエラーを**取得**までは可能である。
しかし、エラーの種類ごとに**対処(例外処理)**をすることができない。

## catchとは？
tryで取得したエラーの種類をもとに、**対処(例外処理)を記述するため**の文。

```java 
try{
    //（上記の）通常処理文
}catch (ArithmeticException e){    //ArithmeticExceptionはゼロが入力された時に起きるエラー。
    System.out.println("0が入力されました。処理を中断します。");
}catch (IOException e){    //文字列が入力できなかった時に起きるエラー
    System.out.println("入力が読み込めませんでした。処理を中断します。");
}
```
※このように、一つ一つのエラーの種類ごとに例外処理を書くことができる。
### すべての例外処理をまとめて処理したい場合

```java 
try{
        //通常処理文
}catch (Exception e){    //Exception とは 例外という意味
        //例外処理分
}
```

## finallyとは？
通常処理終了後も例外処理終了後も**どちらの処理の後でも実行しなければならない処理**を記述する部分

```java 
try {
    //通常処理
}catch (Exception e){
    //例外処理
}finally {
    //最終処理
}
``` 
※try・catch文の最後に書く必要がある。

## throw・throwsとは？

### throwとは？
tryの中で宣言することで**例外処理に処理を移す**ことができる。

```java 
throw new testException();
```

### throwsとは？
メソッドの中で**例外処理が起きる可能性を示しておく**ためにメソッド宣言時に記述する語句。



```java
void show() throws testException{
    // 例外の可能性がある処理
    if (data1 < 0 || data2 > 10000){
        throw new testException();
    }
}
```

***

# 抽象クラスとインターフェイス

## 抽象クラスとは？

クラス宣言時に**abstract**を指定することで作成される、そのままインスタンス化できないクラス。**継承するため**に定義する。
複数のクラスで共通する部分をここで定義する。

```java 
class abstract TestClass {
    //クラスの宣言
}
```

## インターフェイスとは？

abstractでの宣言と同様に、**抽象クラスの宣言**を行うための語句。

```java 
interface TestClass {
    //抽象化するクラスの宣言
}
```

### インターフェイスを使う意味

これを使うことで、**インターフェイスの継承**ができる。

# 参考サイト様

+ http://www.atmarkit.co.jp/ait/articles/0211/29/news004.html
+ http://msugai.fc2web.com/java/permitmod.html
+ http://www.acroquest.co.jp/webworkshop/java_course/J_lecture13.html