# プログラミングA レジュメのまとめ 個人的にやばいところだけまとめてるので不足多い(知るか やばいやつ↓ - ネットワーク(ソケット通信)まわり → 12章 - ストリームまわり - パッケージとかスコープのお話 - スレッドまわり - デザインパターン ## Java仮想マシンのメモリ構造 - ヒープ(Heap):全スレッド共有 - メソッドエリア(Method area):クラスの静的構造の保持 - その他:インスタンスの保持。変数宣言のみではメモリ展開はされない。 - Java仮想マシンスタック(Java VM Stack):スレッド単位 - メソッド起動ごとのフレームが積まれる - 変数の確保等 ## オブジェクト志向の三要素 ### 継承 → クラスの拡張とかそういうお話 ### カプセル化 → アクセス修飾子とかのお話 ### ポリモルフィズム(多態性) → メソッドのオーバーライドのお話 - ポリモーフィズムとも言うよね - 同一メソッド呼び出しが複数の振る舞いを持てる - ある呼び出しに対して実際に呼び出されるインスタンスメソッドが、呼び出し先のインスタンスの型に応じて実行時に決定(動的束縛) - VMはクラス階層の下から上へと探していく(つまり子が優先して実行される) #### メリット - 「呼び出す側」の共通化と再利用 - スーパークラスで宣言されたインスタンスメソッドを呼び出すコードを使いまわせる - 同じコードで複数の異なるインスタンスメソッドを呼び出せる - 例 - 将来のカスタマイズ箇所 - スーパークラスの配列を用意すれば、代入されているインスタンスの型を意識しなくても一様にメソッドを呼び出せる。 ```Java Rectangle[] rcs = new Rectangle[3]; rcs[0] = new NamedRectangle(); rcs[1] = new NamedRectangle(); rcs[2] = new NamedRectangle(); for(Recntagle r : rcs){ System.out.println(r.getSize()); } ``` みたいな感じ ## クラスとインスタンス - モジュール単位・抽象データ型の一種 ### フィールド - クラスやインスタンスが保持するデータ #### インスタンスフィールド - インスタンス固有のデータを保持 - `<インスタンス名>.<フィールド名>`でアクセス可能 #### クラスフィールド - `static`修飾子。クラス定義のみで可。 - クラス固有(全インスタンス共通)のフィールド - `<クラス名>.<フィールド名>`でアクセス可能 ### メソッド #### インスタンスメソッド - インスタンス固有or共通のデータ処理方法の表現 - メソッドの取る不定な引数値を*仮引数*という。 - 呼び出し時実際に与えられる引数値は*実引数*という。 - 名前の衝突が無い場合は`this`は不要(コンパイラが暗黙に付加) #### クラスメソッド - `static`修飾子。クラス定義のみで可。 - `<クラス名>.<メソッド名>`でアクセス可能 - 用途: - クラスフィールドに対する操作 - mainメソッド(自動呼び出し) `public static void main()` - 状態をもたないユーティリティクラス(`java.lang.Math`等) ### コンストラクタ - 一連のインスタンス初期化処理をまとめて実施 - インスタンス生成時に一度だけコール - クラス名と同一、戻り値をとらない - 複数・引数列の異なるコンストラクタを定義可能 - 明示しないと**super()のみ呼び出すデフォルトコンストラクタ**が暗黙に宣言。 - フィールドへの値の代入・参照・メソッド呼び出し等が可能 - this => 実行時点インスタンスを指す予約語 `this.hoge` ```Java public class Kamoku { public Kamoku () { } } ``` ## スーパークラスとサブクラス - クラス階層は、必ず`java.lang.Object`を根とした木構造。 - 無指定のクラスは暗黙に`java.lang.Object`を拡張してることになる - クラスを拡張するには`extends` - 拡張される側のスーパークラスはただ1つ。拡張したクラスはサブクラスという。 ```Java public class Rectangle { } public class NamedRectangle extends Rectangle { } ``` ### 継承 - サブクラスは、自動的にスーパークラスのメソッドやフィールドを**継承**する。 - クラスの**拡張**と、メソッドやフィールドの**継承**。←言葉に注意 - コンストラクタは継承されないが、サブクラスのコンストラクタ内で自動的に呼ばれる。`super()` ### コンストラクタの呼び出し - `super()` - スーパークラスのコンストラクタ - `this()` - 同クラスのコンストラクタを指す。 - 例: `Rectangle()`内から`this("hoge")`とすることで`Rectangle(String str)`を呼べる ### メソッドのオーバーライド - シグニチャ(メソッド名+引数)がスーパークラスのインスタンスメソッドと同一の場合上書き(オーバーライド)可能 - 利用側が期待する意味(contract/契約)を変えないことが条件 - アノテーション`@Override`によりコンパイラチェックが可能 - **クラスメソッドはオーバーライドできないよ!!!** - シグニチャが異なれば違うメソッドとみなされるよ。 - `void setSize(int nw, int nh)`と`void setSize(int nw, int nh, int level)`はシグニチャが異なるので同一クラスに同時に宣言可能 ### フィールドのハイディング - スーパークラスのフィールドと同一名のフィールドを宣言すると、スーパークラスのフィールドは隠される(hiding) - 当然アクセスできないよね - インスタンス/クラス フィールド共に可能 - **混乱しやすいから使うなよ**! ### 予約後superとthis - `super.hoge()`とかってするとスーパークラスの型でメソッド呼べるらしいね ## 例外 ### 例外の定義 - プログラムの誤りを通知し、エラー処理を行うための仕組み - 通常例外発生時は異常終了する。 - 終了せずに対処する仕組み。 ### コールスタック(call stack) - メソッド呼び出しが積まれてる - 通常の呼び出し/returnは呼び出し元に戻る - 例外がスローされると、キャッチされるまでコールスタックを遡る - キャッチされなければそのまま終了 - 全ての例外クラスは、`Throwable`から`printStackTrace()`メソッドを継承してる - 例外スローの**瞬間**のスタックトレースが出力できるよやったね ### 代表的な例外 - java.lang.NumberFormatException - 文字列を数値に変換できない ```Java try { int val = Integer.parseInt(“123”); } catch(java.lang.NumberFormatException nfe) { ... } ``` - java.io.FileNotFoundException - ファイルが見つからない - java.io.IOException - 入出力異常(ファイルが開けなかったとか) ```Java try { FileReader reader = new FileReader(“A.doc”); } catch (java.io.FileNotFoundException fnfe){ } catch (java.io.IOException ioe){ } finally { try { reader.close(); } catch (java.io.IOException ioe) { } } ``` - java.net.MalformedURLException - 指定URLが正しくない ```Java try { java.net.URL = new java.net.URL("htt://abc"); } catch (java.net.MalformedURLException mue) { } ``` ### さまざまな例外 - java.lang.Throwable - java.lang.Error - ↑処理続行不可能 - ↑コンパイラ事前チェック**なし** - java.lang.Exception - java.lang.RuntimeException - ↑実行中に発生 - ↑コンパイラ事前チェック**なし** - それ以外のException - ↑コンパイラ事前チェックあり - ↑投げっぱなしは× ### コンパイラによるチェック #### チェックされるやつ - `RuntimeException`以外の例外はコンパイラによる事前チェックを受ける - どこかでキャッチされてないとエラー - メソッド内の`catch`節でキャッチ or メソッドの`throws`節で投げ出す - 当該例外インスタンスのスーパークラス型(つまり`java.lang.Exception`)でキャッチ可能 - 通常は厳密な型で指定するべき #### チェックされないやつ - java.lang.Error - `java.lang.OutOfMemoryError`(メモリ不足)みたいなの - java.lang.RuntimeException - `java.lang.ArrayIndexOutOfBoundsException`とか - よく起きるのでいちいちthrowsしてたらラチあかない - なのでチェックしない - まあ必要に応じてキャッチしたほうがいいけどネ ### `finally`ブロック - 後始末をかける(例外がキャッチされようがサれまいが実行される) - returnを書かないでね - 「そのキャッチしそこなった例外…消えるよ?」 ### 独自の例外 - 拡張すれば独自の例外が作れるよ - `java.lang.Error`とか`java.lang.RuntimeException`はコンパイラにチェックしてもらえないから避けようね ## インターフェース・抽象クラス ### インターフェースとは - 以下を持つ参照型。 - **定数**フィールド - 自動的に`public static final` - `int HOGE_FUGA = 0;`みたいに名前は大文字にしたほうが定数っぽくてわかりやすい - **抽象**メソッド - インスタンスメソッドのみ - 自動的に`public abstract` ### インターフェースの実装 - `<クラス名> implements <インターフェース名>, <インターフェース名>, ...` - インターフェースが持つ抽象かつインスタンスメソッドの実装(本体定義)を強制 - 実装するメソッドの可視性は必ず**public** - あるクラスで一度実装すると、そのサブクラスは自動的に実装していることになる。 - インターフェースを実装したクラス内では`<インターフェース名>.<フィールド名>`でインターフェースのフィールドを参照可能(衝突してない場合のみ省略可能) ```Java interface DebugPrintable { int NO_ERROR = 0; int FILE_ERROR = 1; String PREFIX = "DEBUG:"; void debugPrint(); } class MyNumber implements DebugPrintable { public void debugPrint() { System.out.println(PREFIX + "MyNumber: " + number); System.out.println(DebugPrintable.PREFIX + "MyNumber: " + number); } } ``` ### インターフェース型変数 - 当該インターフェースを実装したあらゆるクラスのインスタンスを代入可能 - インターフェースそのもののインスタンスは作成不可能 ```Java DebugPrintable d1 = new Rectangle(200,200); DebugPrintable d2 = new MyNumber(999); //同じ呼び出しだが異なるメソッドが呼ばれる d1.debugPrint(); d2.debugPrint(); ``` ### インターフェースの役割 - 階層上の異なる位置のクラス群に共通の手続きを追加する。 - 階層上の異なる位置のクラス群を一様に扱う - いわば「マーキング」 - 多態性の実現 - クラス拡張と似て非なるもの。「階層」というより「横断」 ### 使い所 #### 呼び出し側の再利用 - 配列 - 配列中の各要素に対し、クラスの違いに関わらずインターフェースのメソッドを呼び出せる ```Java DebugPrintable set = new DebugPrintable[5]; set[0] = new Rectangle(200,100); set[1] = new MyNumber(999); ... set[4] = ...; for(int i = 0; i < set.length; i++){ set[i].debugPrint(); } ``` - メソッドの引数 - インスタンスの型の違いに関わらずインターフェースのインスタンスメソッドを呼び出せる ```Java class MyInspector { void inspect(DebugPrintable d){ d.debugPrint(); } } ``` #### 擬似的な多重継承 - 拡張は1つのクラスのみ - 実装は必要だが擬似的にメソッドを多重継承できる ### インターフェースの拡張 - 拡張によりスーパーインターフェースのメソッド/フィールドを継承 - サブに加えスーパーのメソッドも実装する必要あり ```Java interface DebugPrintable { int NO_ERROR = 0; int FILE_ERROR = 1; String PREFIX = "DEBUG:"; void debugPrint(); } interface AnotherPrintable extends DebugPrintable { double anotherField = 0.0; String anotherMethod(); } class MyNumber implements AnotherPrintable { public void debugPrint(){ // } public String anotherMethod(){ return ...; } } ``` ### 抽象クラス ```Java abstract class AbstractClassTest{ abstract void hook(); public static void main(String[] args){ AbstractClassTest c = new ConcreteClass(); c.hook(); } } class ConcreteClass extends AbstractClassTest { //Interfaceと違って修飾子はpublicと明示しなくてもいい void hook() { System.out.println("ConcreteClass.hook()"); } } ``` ## ガーベッジコレクション ### ガーベッジコレクタとは - 誰からも参照されないゴミ(ガーベッジ)をヒープから取り除き、占拠されていたヒープを再び利用できるようにする仕組み ### ガーベッジコレクションとは - ガーベッジコレクタによるガーベッジ収集とメモリ再利用 - ヒープの空きが「ある程度」不足してきたら自動的にJavaVMが実行(処理系依存) - **メモリが完全に枯渇した時ではない**←重要 - このときはOutOfMemoryErrorが投げられる - GC実行中は一時的に動作を「停止」 ### メモリ関連のクラス・メソッド - java.lang.Systemクラス - public static void gc() - ガーベッジコレクションの強制実行 - java.lang.Runtimeクラス - public static Runtime getRuntime() - 現在のRuntime インスタンス取得 - public long freeMemory() - 空きメモリサイズ (= total - 利用メモリサイズ) - public long totalMemory() - 利用可能全メモリサイズ - public long maxMemory() - JavaVM起動時に指定した最 大メモリサイズ ### finalizeメソッド - Objectクラスの`protectedvoidfinalize()`メソッド - 収集される前にいつか呼ばれる - メモリや資源の明示的な解放用メソッドとすべきではない→独自メソッド(`close()`等)を宣言して代用する ## スレッド ## マルチスレッドデザインパターン ## パッケージ ## ファイル操作と入出力 ### Javaにおける入出力 - java.io パッケージ: input/output - ストリーム(データの連続的な流れ) - バイトストリーム - バイト(byte,8bit)単位の入出力 - **任意**の(テキスト以外)データファイルを扱う場合 - InputStream, OutputStream - 文字ストリーム - 文字(char,16bit)単位の入出力 - **文字やテキストファイル**を扱う場合 - 内部で扱う文字コードは**Unicode** - Reader, Writer ### バイトストリーム #### 入力:InputStream ```Java int data = 0; try { FileInputStream fis = new FileInputStream("foo.dat"); while((data = fis.read()) != -1) { //データ処理 } fis.close(); } catch(FileNotFoundException fnfe) { } catch(IOException ioe) { } ``` #### 出力:OutputStream ```Java try { FileOutputStream fos = new FileOutputStream("bar.doc"); fos.write(255); System.out.write(255); fos.close(); } catch(IOException ioe) { } ``` #### バッファリング:Buffered~ ```Java InputStream is = new BufferedInputStream(new FileInputStream(args[0])); OutputStream os = new BufferedOutputStream(new FileOutputStream(args[1])); ``` #### Decoratorパターン - 上記のようなメソッドの入れ子によって機能追加をしていけるような構造 ### 文字ストリーム #### 入力:Reader ```Java try { BufferedReader reader = new BufferedReader(new FileReader(args[0])); String line = null; while ((line = reader.readLine()) != null) { System.out.println(line); } reader.close(); } catch (FileNotFoundException e) { } catch (IOException e) { } ``` #### 出力:Writer ```Java String filenale = args[0]; try { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(filename))); String line = null; while ((line = reader.readLine()) != null) { writer.println(line); } reader.close(); writer.close(); } catch (IOException e){ } ``` ### ファイル・ディレクトリ操作 - java.io.Fileクラスを使えばファイル削除やリネームができる - 取得系 - boolean isFile() : ファイルか確認 - boolean isDirectory() : ディレクトリか確認 - String[] list() : 当該ディレクトリのファイル・ディレクトリ一覧 - String getAbsolutePath() : 絶対パスの取得 - File getParentFile() : 親ファイルの取得 - String getParent() : 親ファイルのパス名 ## ネットワーク ## コレクション