Javaの仕様メモ

あまり他人に読ませるつもりでまとめていない、自分用メモ。

## Primitive Type

* 数値型にunsignedはない
* NaNや +0.0 と -0.0 の比較のため、浮動小数点は == じゃなくて Double.compare を使う

## 継承

継承の例:

```java
interface Foo {
    void bar();
}

class Foo extends Bar implements Foo {
    ...
}
```

### 複数継承
* C++と違ってクラスの複数継承はできない

### 演算子

* C++と違ってoperator overloadingはできない

### equalsのオーバーライド
* 以下の規則を満たすように実装する:
  * 反射的 (reflexive): x.equals(x) は true
  * 対称的 (symmetric): y.equals(x) が true の場合のみ、x.equals(y) も true
  * 推移的 (transitive): x.equals(y) 、y.equals(z) が true ならば、x.equals(z) も true
  * 整合的 (consistent): 情報が変更されなければ、x.equals(y) の結果は不変
* hashCodeもオーバーライドする


## final, finally, finalize

### final

* クラス: 継承できる
* メソッド: オーバーライドできない
* 変数: 変更できない


### finally

* return, continue, breakや例外など、通常は何をやってもfinallyは実行される
  * スレッドやVMが突然死んだ場合は実行されない
  * System#exit や Runtime#exit でも実行されない

### finalize

* JVMがオブジェクトをGCする前に走らせるメソッド
* Java 9でdeprecatedなので覚えておく必要はない


## 修飾子

### abstract 

* クラス: abstractメソッドを持つ。instantiateできない。
* インターフェース: 全てのinterfaceは非明示的にabstractになっているので、abstractは書かなくてもよい
* メソッド: 定義を持たないメソッド。クラスもabstractでないといけない。

### protected

* メソッド、変数にのみ付与可能
* 同一クラス、サブクラスから参照できる

### private

* コンストラクタをprivateにするとそのクラス外でクラスをinstantiateできなくなる。
  * Factory Method パターンでstatic publicメソッドからのみ作るのに使われる。
  * 継承は不可能になる

### static

* メソッド: クラスメソッドになる
* 変数: クラス変数になる。クラスに1つになり、クラス名からアクセス可能

### volatile
* マルチスレッド環境のため、スレッド間のフィールド値のキャッシュを防ぎ、また代入処理などのreoderを防ぐ
* 更新に依存関係がある場合などはvolatileは不十分で、synchronizedブロックを使わなければいけない

## クラス

### 外部クラス
* 内部クラスを持つクラスのこと
* **外部クラスにはstaticは存在しない**
* **外部クラスにはprivateも書けない**
  * デフォルトでは同パッケージ内からのみアクセス可能、publicにすると別パッケージから使える
  * publicなクラスはファイル名も揃える必要がある

### 内部クラス
* 外部クラスにネストして定義するクラス。外部クラスでないクラスからでも使える
* 外部クラスのオブジェクトから内部クラスをinstantiateすると、外部クラスのメンバにアクセスできる
* **非static 内部クラスはstaticなコンテキストからinstantiateできない**

### ローカルクラス
* 外部クラスのメソッド内で定義したクラス
* 内部クラスの一種なので、staticなフィールドやメソッドは作れない

### static 内部クラス
* 内部クラスと全く挙動が異なる
* 外部クラスのオブジェクトからではなく、外部クラスからinstantiateする
* 当然外部クラスの非staticなメンバにアクセスできない。staticならアクセスできる

### String

* ==: Stringは == で比較してはいけない
* +: Javaの文字列連結は内部的にStringBuilderを使うので、+でStringを連結しまくると遅い
* length(): Unicodeコード単位の数を返すだけなので、サロゲートペアを含むで期待通り動作しない。codePointCountを使う
* String#split はPatternではなくStringとして正規表現を取る

### Integer

* コンストラクタではなく Integer.valueOf(int) などのファクトリメソッドを利用するようにする。インスタンスが使い回されるかもしれないため。

### Deque
Double-ended queue。Queue interfaceを実装しているのでQueueとして使えるが、Stackはclassなので実装していない。
一方、[StackよりもDequeを使う](https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html)ようにStackのドキュメントで推奨されているので、Stack風のinterfaceが要る時はDequeを使うべきである。StackはVectorを実装しており、本来不要そうなインデックスアクセスができる。

一般に、LinkedListは全操作が$O(1)$で、ArrayDequeのような実装だと追加の最悪計算時間が$O(n)$になるものの、全ての操作のTime ComplexityはAmortized Analysisで$O(1)$になる。

### ヒープの連続領域を確保するクラス

* ByteArrayOutputStream
* Buffered\* (BufferedInputStream)
* ArrayList
* String
* StringBuilder

メモリの使いすぎに注意

### レガシークラス

* Vector => ArrayList
* Stack => LinkedList
* HashMap => Hashtable
* StringBuffer => StringBuffer


## 比較
任意クラスの比較を実装する方法は主に2つある。

### Comparable.compareTo
```java
class Foo implements Comparable<Foo> {
    int key;

    public Foo(int key) { 
        this.key = key;
    }

    @Override
    public int compareTo(Foo f){
        return this.key - f.key;
    }
}

Collections.sort(fooList);
Collections.sort(fooList, Collections.reverseOrder());
```

### Comparator.compare
```java 
class FooComparator implements Comparator<Foo> {
    @Override
    public int compare(Foo a, Foo b) {
        return a.key - b.key;
    }
}

Collections.sort(fooList, new FooComparator());
```


## スレッド

使い方の例

```java
class Foo implements Runnable {
    public void run() {
        while (true) System.out.print(".");
    }
}

Foo foo = new Foo();
Thread thread = new Thread(foo);
thread.start();
```

### スレッドセーフではないクラス

* SimpleDateFormat
* ...

並行にアクセスがある際 synchronized などで扱う必要がある


## 参照
参照には以下の種類がある:

* Strong: 普通の参照
* Weak: String referenceがなくなるとGCされる参照
* Soft: Weakと違い必ず消えるとは限らず、本当にメモリが必要な場合のみ消される。GCはOutOfMemoryErrorになる前にこれはクリーンアップする必要がある
* Phantom: finalizeを自分でスケジューリングするために使う https://qiita.com/yoshi389111/items/66448f9a013eee4be035

https://docs.oracle.com/javase/jp/8/docs/api/java/lang/ref/Reference.html

## Generics

* クラスもメソッドもジェネリックにできる
* Primitive Typeはパラメータにできない
* `? super Xxx` や `? extends Xxx` を書いて bounded type parameter を定義できる
* Parameter Typeはinstantiateできない
* staticなメソッドや変数にParameter Typeを利用できない

## その他後で調べたいもの

* object reflection: `Class.forName` など
* class loader
* dependency injection