java何でもメモ

こっそり、、勉強中
忘れてググる自分用

# 定数

```java
final データ型 定数名 = 値
```

# null
参照先がない状態のこと
空("")の文字列は、参照先に空の文字列がある状態なので、nullではない
→プリミティブ型には、nullという状態はない

## 比較したい
nullでは、equalsメソッドを使うと、例外が発生する。（NullPointerException）
「==」演算子を使う。


### 空文字は
「isEmpty」メソッドを使うとよい

# 継承
既存のクラスを拡張して作れる
サブクラスはスーパークラスのフィールド、メソッドを引き継ぐ。
スーパークラスのメソッドにアクセスするには、superキーワードを使う
サブクラスのメソッドにアクセスするには、thisキーワードを使う。
スーパークラスは１つで、サブクラスは複数いる。

```java
super.hoge();
```

## オーバライド
親のメソッド名、戻り値、引数を一致させたものを子クラスに実装する
明示的に「@Override」をつけるといいらしい。

```java
//子クラス
@Override
void hoge(){
}
```

オーバライドしたメソッドは、サブクラスのものが優先される。

# 抽象クラス
インスタンスを作れないクラス

```java
abstract class TestClass {
    void test() {
        System.out.println("TEST");
    }
}
public class SampleProgram {
    public static void main(String[] args) {
        //コンパイルエラー：型 TestClass のインスタンスを生成できません
        TestClass tc = new TestClass();
    }
}
```

# 抽象メソッド

- メソッド内に命令の入ってないメソッドのこと
- 抽象メソッドは、抽象クラスに定義する
- 抽象クラスを継承したサブクラスは、抽象メソッドをオーバーライドしない限り抽象クラスのまま（？？）


```java
abstract class TestClass {
    //普通のメソッド
    void test() {
        System.out.println("TEST");
    }
    //抽象メソッド
    abstract void test2();
}

abstract class TestClass {
    //コンパイルエラー：抽象メソッドは本文を指定しません
    abstract void test() {
        System.out.println("TEST");
    }
}
```

抽象クラスを継承しても、サブクラスを抽象クラスに定義すれば、オーバーライドが必要ないってことなのかな。。

```java
abstract class TestClass {
    //普通のメソッド
    void test() {
        System.out.println("TEST");
    }
    //抽象メソッド
    abstract void test2();
}

//コンパイルエラーにならない
abstract class subClass extends TestClass {
}

//コンパイルエラー：型 subClass は継承された抽象メソッド TestClass.test2() を実装する必要があります
class subClass extends TestClass {
}
````

# インターフェース

- クラスが持つべき、メソッドを定義したもの
- インターフェースで定義したものは、クラスで実装する
- クラスで実装するものは、インターフェースで定義したメソッドすべて。
- 継承のように、１対Ｎではなく。Ｎ対Ｎの多重継承ができる。
- インターフェースで定義されたメソッドは、暗黙的に「public abstract」修飾子付きとして扱われるので、実装する際は、必ず「public」修飾子を付ける。
- クラスでインターフェースを実装するときは、インターフェースを「,」で区切る
- メソッドだけじゃなくて、定数も定義できる
インターフェースのフィールドで定義された変数は、修飾子なしで、暗黙的に
「public static final」付き、つまり、定数になる。
- インターフェースもインターフェースを継承できる。

```java
interface testIf{
    int test();
    void test2(String msg);
}
```

```java
interface testIf{
    void test2(String msg);
}
//コンパイルエラー：型 test は継承された抽象メソッド testIf.test2(String) を実装する必要があります
class test implements testIf{

}

//コンパイルエラー：testIf から継承されたメソッドの可視性を下げることはできません
class test implements testIf{
    void test2(String msg) {
        System.out.println(msg);
    }
}

// コンパイルエラーなし
class test implements testIf{
    public void test2(String msg) {
        System.out.println(msg);
    }
}

```

## インターフェースを複数継承

```java
interface testIf1{
    void test1(String msg);
}

interface testIf2{
    int test2();
}

class test implements testIf1, testIf2{
    public void test1(String msg) {
        System.out.println(msg);
    }

    public int test2() {
        return 1;
    }
}
```

## インターフェースで定数定義

```java
interface testIf1{
    int HOGE = 1;
    public static final String HOGE2 = "定数";
}

class test implements testIf1{
    int i = testIf1.HOGE;
    //コンパイルエラー：final フィールド testIf1.HOGE には代入できません
    //testIf1.HOGE = 1;
    void testPrint() {
        System.out.println(testIf1.HOGE2);
    }
}

public class SampleProgram {
    public static void main(String[] args) {
        test t = new test();
        t.testPrint();
    }
}

```

## インターフェースの継承

```java
interface testIf1{
    int HOGE = 1;
    public static final String HOGE2 = "定数";
    void test();
    void test2();
}
//インターフェースの継承
interface testIf2 extends testIf1{
    void test();
}

//コンパイルエラー：型 test は継承された抽象メソッド testIf1.test2() を実装する必要があります
class test implements testIf2{

    @Override
    public void test() {
        // TODO 自動生成されたメソッド・スタブ
    }
}

//コンパイルエラーなし
class test implements testIf2{

    @Override
    public void test() {
        // TODO 自動生成されたメソッド・スタブ
    }

    @Override
    public void test2() {
        // TODO 自動生成されたメソッド・スタブ        
    }
}
```

親インターフェースと、子インターフェースで同じメソッド定義があっても、エラー扱いにはならないんだなぁ。。混乱のもとにはなりそうだけど。




# ポリモーフィズム
日本語では多態性（多様な動作をする）という意味。

- スーパークラスの型の変数に、サブクラスのインスタンスを代入できる
- インターフェースの型の変数に、インターフェースを実装したクラスのインスタンスを代入できる
- メソッドを呼び出すと、変数の型に関係なく、変数が参照するメソッドが実行される。（難しい。。）

```java
import java.util.ArrayList;
import java.util.List;

interface TestIf{
    public abstract void run();
}

class TestAAA implements TestIf{

    String myClassName = "TestAAA";
    @Override
    public void run() {
        // TODO 自動生成されたメソッド・スタブ
        System.out.println(myClassName);
    }
}


class TestBBB implements TestIf{

    String myClassName = "TestBBB";
    @Override
    public void run() {
        // TODO 自動生成されたメソッド・スタブ
        System.out.println(myClassName);
    }
}


public class SampleProgram {
    public static void main(String[] args) {

        //インターフェース型のコレクション、配列を用意
        List<TestIf> list = new ArrayList<TestIf>();
        TestIf[] array = new TestIf[2];

        //コレクションに各インスタンスを設定
        list.add(new TestAAA());
        list.add(new TestBBB());

        //配列に各インスタンスを設定
        array[0] = new TestAAA();
        array[1] = new TestBBB();

        System.out.println("コレクション");
        for(TestIf ti: list) {
            ti.run();
        }
        System.out.println("配列");
        for(int i = 0; i < array.length; i++) {
            array[i].run();
        }

    }
}
```

# コピー

## 配列のコピー

array2は、array1の参照になる。
array2の要素を書き換えると、array1にも影響する。
逆も同じ。

```java
int[] array1 = {1,2,3};
int[] array2 = array1;

```
cloneメソッドを使えば、値のコピーができる。
コレクションも同様。
```java
int[] array2 = array1.clone();
```

### シャローコピー、ディープコピー
cloneメソッドでは不十分な時がある。
要素がプリミティブ型ではなく、オブジェクト型の場合
オブジェクト型は値ではなく、参照先を要素としているので、参照先にある値までコピーはしない。これをシャローコピーという。
これだと、複数のオブジェクトで同じ値を共有することになる。
参照先の値までコピーするのをディープコピー。
どこまでコピーするかはプログラム次第。

大変そう。。

# ジャネリクス(Generics)
型を「<」「>」で囲んで、表記することで、型を強制するための指定

## ジェネリクスを使ったパターン
String型しか入らない。

```java

List<String> list = new ArrayList<String>();
```

## ジェネリクスを使ってないパターン
Eclipse上で注意メッセージは出るけど使える。
データの型を指定しないので、プリミティブ型以外は何でもはいる。

```java

List list = new ArrayList();
````

### ジェネリクスの利点

- 明示的なキャストがいらない
- キャストは処理を遅くする可能性がある
- どんなデータが入るかわかりやすい

```java
List list = new ArrayList();
List<String> list2 = new ArrayList<String>();

// キャストが複雑
System.out.println(((String) list.get(0)).length());
// 普通のString型と同じように使える
System.out.println(list2.get(0).length());
```
確かに、ジェネリクスを使ったほうが、楽かも。
Eclipseくんは優秀だけど。



# 配列

## 配列の要素数

```java
配列名.length
```

# 繰り返し色々
## 基本
```java
public class SampleProgram {

    public static void main(String[] args) {
        int[] box = {0,1,2,3,4,5,6,7,8,9};

        for(int i = 0; i < 10; i++) {
            if(i == 5) {
                System.out.println(i+1+":"+box[i]+"_continue");
                continue;
            }else if(i == 7) {
                System.out.println(i+1+":"+box[i]+"_break");
                break;
            }
            System.out.println(i+1+":"+box[i]);
        }
    }
}

//結果
1:0
2:1
3:2
4:3
5:4
6:5_continue
7:6
8:7_break
```

```java
public class SampleProgram {

    public static void main(String[] args) {
        int[] box = {0,1,2,3,4,5,6,7,8,9};
        int i = 0;
        while(i < 10) {
            System.out.println(i+1+":"+box[i]);
            i++;
        }
    }
}

public class SampleProgram {

    public static void main(String[] args) {
        int[] box = {0,1,2,3,4,5,6,7,8,9};
        int i = 0;
        do {
            System.out.println(i+1+":"+box[i]);
            i++;
        }while(i < 10);
    }
}

```

do~whileなんて久しぶりに見たな・・
添え字って増えてくると、名前のストックがなくなってくる。。


## 拡張For文

```java
import java.util.HashSet;
import java.util.Set;

public class SampleProgram {

    public static void main(String[] args) {
        // 値の重複を許さない
        // 順序の保証もない
        Set<String> hs = new HashSet<String>();
        hs.add("白");
        hs.add("赤");
        hs.add("白");
        hs.add("緑");

        int[] array = {1,2,3,1};

        // HashSetにはgetメソッドがない
//        for(int i = 0; i < hs.size(); i++) {
//            System.out.println(hs.(i));
//        }

        // 拡張for 文
        for(String item : hs) {
            System.out.println(item);
        }

        for(int i : array) {
            System.out.println(i);
        }
    }
}

//結果
緑
赤
白
1
2
3
1

```

## ラムダ式
むずかしい・・


## いろいろ
```java

public class TestMain {
    public static void main(String[] args) {
        List<String> cities = new ArrayList<String>();
        cities.add("京都");
        cities.add("大阪");
        cities.add("愛知");

        System.out.println("ループ１");
        for(int i = 0; i < cities.size(); i++) {
            System.out.println(cities.get(i));
        }
        System.out.println("ループ２");
        for(Iterator<String> ite = cities.iterator(); ite.hasNext();) {
            System.out.println(ite.next());
        }
        System.out.println("ループ３：拡張forループ");
        for(String city : cities) {
            System.out.println(city);
        }

        System.out.println("ループ４：");
        cities.forEach(new Consumer<String>() {
            public void accept(final String citiy) {
                System.out.println(citiy);
            }
        });

        System.out.println("ループ５：ラムダ式");
        cities.forEach((final String city) -> System.out.println(city));

        System.out.println("ループ６：ラムダ式");
        cities.forEach(System.out::println);
    }

}

```

## map
### キーと値の一覧の繰り返し

```java
import java.util.HashMap;
import java.util.Map;
public class SampleProgram {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<String, String>(){
            {
                put("001","赤");
                put("002","青");
                put("003","緑");
            }
        };

        // 値
        for(String item : map.values()) {
            System.out.println(item);
        }

        // キー
        for(String item : map.keySet()) {
            System.out.println(item);
        }
    }
}
```


# デフォルトエンコーディング

## javac でコンパイルするとき

サクラエディタや、メモ帳で何気なく、ソースコードを書き

```java
javac hoge.java
```

と何気なく、コンパイルしたり
Eclipse上でボタンをぽちっとして実行したりしてるだけだと気づかなかった。
Eclipse上で作成したソースコードを、DOS上で手動でコンパイルしたら

```java

//ソースコード
public class SampleProgram {
    public static void main(String[] args) {
    	System.out.println("ほげ");
    }
}

//結果
C:\MyWork\>javac SampleProgram.java
SampleProgram.java:6: エラー: この文字は、エンコーディングMS932にマップできません
        System.out.println("縺ｻ縺?");
                               ^
エラー1個

C:\MyWork\>
```

これは、ソースファイルが「UTF-8」で、Windowsのデフォルトエンコーディングが「MS932」の不一致で発生する。
javacでコンパイルするときに、エンコーディングを指定しないと、JVM（？）のデフォルトエンコーディングでコンパイルされる。
環境がWindowsで、ファイルのエンコーディングが「UTF-8」なら、

```
javac -encoding utf8 SampleProgram.java
```

とすれば無事コンパイル出来る。


## デフォルトエンコーディングの確認の仕方

```java
import java.util.Properties;
import java.util.Enumeration;

class sampleEncoding{
  public static void main(String args[]){
    System.out.println(System.getProperty("file.encoding"));
  }
}

```

## デフォルトエンコーディングの変更
デフォルトエンコーディングはJavaプログラムで入出力でも影響があるらしく。
ファイルを読み込んだりするときに、ファイルのエンコードを指定しないと
デフォルトエンコーディングが使われるみたいなので、
デフォルトエンコーディングが「utf8」の環境で、
読み込むファイルが「euc」の場合、エンコーディングを指定しないと
文字化けを起こす。

デフォルトエンコーディングを事前に変更しておけば、ソースコードや入力ファイルを修正
しなくても、一応文字化けしないし、コンパイルも出来る。

```
REM windowsの場合
set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8


C:\MyWork>javac SampleProgram.java
SampleProgram.java:6: エラー: この文字は、エンコーディングMS932にマップできません
        System.out.println("縺ｻ縺?");
                               ^
エラー1個

C:\MyWork>set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8

C:\MyWork>javac SampleProgram.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8

C:\MyWork>
```



# 金銭計算の時は、floatやdoubleを使わない
内部で2進数に変換されて計算されるときに、誤差が生じるらしい

BigDecimalクラスを使うらしい。
２進数に変換せず計算するらしい。

```java
import java.math.BigDecimal;

public class SampleProgram {

    public static void main(String[] args) {
        double xx = 1.0;
        double yy = 0.9;
        System.out.println(xx - yy);
        System.out.println(xx / yy);

        BigDecimal x = new BigDecimal("1.0");
        BigDecimal y = new BigDecimal("0.9");

        System.out.println(x.subtract(y));
        System.out.println(x.divide(y, 2, BigDecimal.ROUND_UP));
        System.out.println(x.divide(y, 2, BigDecimal.ROUND_DOWN));
        System.out.println(x.divide(y, 2, BigDecimal.ROUND_HALF_UP));
        System.out.println(x.divide(y, 3, BigDecimal.ROUND_HALF_DOWN));
        System.out.println(x.divide(y, 2, BigDecimal.ROUND_HALF_UP));
        System.out.println(x.divide(y, 3, BigDecimal.ROUND_HALF_DOWN));
    }

}


//結果
0.09999999999999998
1.1111111111111112
0.1
1.12
1.11
1.11
1.111
1.11
1.111

```

BigDecimal.ROUND_HALF_UPと、BigDecimal.ROUND_HALF_DOWNは何が違うのだろうか・・
コメントをもらって、改めて調べた結果
BigDecimal.ROUND_HALF_UPは、四捨五入
BigDecimal.ROUND_HALF_DOWNは、五捨六入
でした。
全然違うんですねぇ。。。

```java
import java.math.BigDecimal;
import java.text.DecimalFormat;

public class SampleProgram {

    public static void main(String[] args) {

        DecimalFormat format = new DecimalFormat("#.#");
        BigDecimal x = new BigDecimal("10.55");



        BigDecimal xx = x.setScale(1, BigDecimal.ROUND_HALF_UP);
        System.out.println("小数第２位で四捨五入 : " + format.format(xx));

        BigDecimal xxx = x.setScale(1, BigDecimal.ROUND_HALF_DOWN);
        System.out.println("小数第２位で五捨六入 : " + format.format(xxx));

    }

}

//結果
小数第２位で四捨五入 : 10.6
小数第２位で五捨六入 : 10.5

```

ちなみに、divideに割る数だけしか指定しないと、以下の例外が・・・
計算結果が循環小数になるのが原因らしい

```java
System.out.println(x.divide(y));

//例外
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
	at java.math.BigDecimal.divide(BigDecimal.java:1690)
	at SampleProgram.main(SampleProgram.java:15)

```

# 数字のソース上の見栄え
「_」で区切りをつけることができる。
表示結果、計算に影響が出ない。うーん。。。定数定義とかなら便利か？

```java
int x = 1_000;

```

# 違う型に代入したい

## キャストは相互性があるものしか使えない

```java
int x = 12;
int y = 5;
double ans = (double)x / (double)y;
```
### 相互関係にあるもの

- プリミティブ型同士
- クラスの継承元が同じ
- 同じインターフェースが実装されている

## でも、数値を文字列に変換したい

String.valueOfメソッドを使う
使い方は、
クラス名.メソッド名

```java
int x = 1234;
String ss = String.valueOf(x);

```
文字列型になったので、lengthメソッドが使える。

```java
public class SampleProgram {

    public static void main(String[] args) {
        int x;
        x = 123 * 234;
        System.out.println(String.valueOf(x).length());
    }

}
```

クラスに対して呼び出すメソッドを
 
- 静的メソッド
- staticメソッド
- クラスメソッド

という、逆にオブジェクトに対して（変数に対して）呼び出すメソッドを
instanceメソッドという。

見分け方は、「static」があるかないか。

## 文字列を数字にしたい

プリミティブ型をラッパークラスを使って、オブジェクトに変換する。

| プリミティブ型 | ラッパークラス |
|:-:|:-:|
| boolean  | Boolean  |
| char  |  Character |
| byte  | Byte  |
| short  | Short  |
| int  | Integer  |
| long  |  Long |
| float  | Float  |
| double  |  Double |

```java
import java.io.IOException;

public class SampleProgram {

    public static void main(String[] args) throws IOException {
       String x = "123";
       String xx = "12.45";
       int y;
       double yy;

       // String型へ、プリミティブ型は代入できない
       //y = x;

       y = Integer.valueOf(x);
       System.out.println(y);
       yy = Double.valueOf(xx);
       System.out.println(yy);
    }
}
//結果
123
12.45

```
### まとめ

- プリミティブ型同士は、キャストで対応（ex. (double)i / (double)ii）
- String型→プリミティブ型は、Stringクラスのメソッドで対応
- プリミティブ型→String型は、ラッパークラスで対応


## ファイルの入出力
### 入力１
ただclose()を書くと、「処理されない例外の型 IOException」とエラーになってしまうので、スロー宣言の追加してます。。
(java1.6が現役のプロジェクトってまだまだあるんだな。。って思う２０２１年）

```java
package prototype.test.readfile;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
		System.out.println("Start.......");
		// Fileオブジェクトは文字列が書き込まれているファイルを表す
		String filePath = "C:\\MyWork\\work\\eclipse-workspace\\file\\input.txt";
		File file = new File(filePath);
		BufferedReader br =null;
		try {
			// Fileオブジェクトから文字列を受け取る
			FileReader fr = new FileReader(file);
			// 受け取った文字列を蓄えておき、要求に応じて文字列を渡す
			br = new BufferedReader(fr);
			String line = null;
			while((line = br.readLine()) != null) {
				System.out.println(line);
			}
		} catch (FileNotFoundException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}finally {
			System.out.println("close!!");
			br.close();
		}
		System.out.println("End.........");
		
	}
}

//結果
Start.......
Test 1
Test 2
close!!
End.........

```
### 入力２
入力１のtyr-catch文をtry-with-resources文に変更。

```java
package prototype.test.readfile;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * try-with-resourcesを使ったバージョン
 * java1.7から仕様可能
 *
 */
public class Main2 {
	public static void main(String[] args) throws IOException {
		System.out.println("Start.......");
		String filePath = "C:\\MyWork\\work\\eclipse-workspace\\file\\input.txt";
		File file = new File(filePath);

		try(
			//リソースの宣言 ここで宣言した変数に対して、自動的にclose()メソッドが呼ばれる
			FileReader fr = new FileReader(file);
			BufferedReader  br = new BufferedReader(fr);
			)
		{
			String line = null;
			while((line = br.readLine()) != null) {
				System.out.println(line);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("End.........");
		
	}

}

```

## enum

```java
--Const.java
package prototype.test.Const;

public class Const {
	public static enum PEN {
		pencil("えんぴつ"),
		ballpoint_pen("ボールペン"),
		fountain_pen("万年筆");

		private String name;

		/**
		 * プライベートコンストラクタ 列挙型のインスタンス生成を抑止します
		 */
		private PEN(String name) {
			this.name = name;
		}

		public String getValue() {
			return this.name;
		}

	}
}
--Main2.java
package prototype.test.Const;

import prototype.test.Const.Const.PEN;

public class Main2 {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		String pen = "えんぴつ";
		System.out.println("pen["+pen+"]");
		if(PEN.pencil.getValue().equals(pen)) {
			System.out.println("OK");
		}else {
			System.out.println("NG");
		}
	}

}

````


## 条件の書き方

### IF文
いろんな言語をやり始めると、「else if」の書き方がわからなくなる。。

#### 基本形
```
if(条件１) {
    
}else if(条件２) {
    
}else {
    
}
```

#### 比較演算子

| 演算子 | 意味 |
|:-:|:-:|
| ==  | 等しい  |
| !=  | 異なる  |
| >  |  - |
| >=  | -  |
| <  |  - |
| <=  | -  |

#### 論理演算子

- AND：&&
- OR：||
- NOT：!

##### 「==」と「equals」

「==」はオブジェクト(アドレス)が同じであるかを判断するもの、
値が同じであるかは「equals」を使う。
「equals」はプリミティブ型以外の型には備わっている。

（参照型と、基本型の違い。基本型は値が格納されているが、参照型は、オブジェクトのアドレスが格納されているから。。？？）

# 正規表現
難しい。。

```
public class SampleProgram {

    public static void main(String[] args)  {

        String[] tell = {"090-1234-1234","1234-1234-1234","090-O123-1234"};
        /*
         * 3桁の数字 - 4桁の数字 - 4桁の数字
         */
        for(int i = 0; i < tell.length; i++) {
            System.out.println(tell[i]);
            if(tell[i].matches("\\d{3}-\\d{4}-\\d{4}")) {
                System.out.println("正解");
            }else {
                System.out.println("不正解");
            }
        }

    }

}

//結果
090-1234-1234
正解
1234-1234-1234
不正解
090-O123-1234
不正解

```

# 例外

## 基本形
finallyはあんまり使わないのかな。。

```
try{

}catch(例外のクラス 変数名){

}finally{

}
```

## メソッドの外へ投げる
メソッド内で例外が発生した場合に、同メソッド内でキャッチせずに、メソッドの外へ投げることができる。外で例外をキャッチしないといけない。

```
戻り値 メソッド名(引数) throws 例外の型 {

}
```

try-with-resources構文というのもあるのか。。。
Java7からの機能らしい。
~~今は置いておこう。。~~
コメントで使い方を教えてもらいました！
便利かも。

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

public class SampleProgram {
    public static void main(String[] args) {
        String fileName1 =  "C:\\test3.txt";
        String fileName2 = "C:\\test4.txt";

        //String fileName1 = null;

        try (
                FileReader fr = new FileReader(new File(fileName1));
                BufferedReader bfr = new BufferedReader(fr);
                FileReader fr2 = new FileReader(new File(fileName2));
                BufferedReader bfr2 = new BufferedReader(fr2);

             )
        {
            String ss = null;

            while((ss = bfr.readLine()) != null) {
                System.out.println(ss + "を読み込みました");
                //throw new IOException();
            }
        }catch(IOException e) {
            e.printStackTrace();
        }
    }
}

```


```
//基本形
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class SampleProgram {

    public static void main(String[] args)  {

        try {
            File file = new File("C:\\test3.txt");
            FileReader fr = new FileReader(file);
            BufferedReader bfr = new BufferedReader(fr);
            String ss = null;

            while((ss = bfr.readLine()) != null) {
                System.out.println(ss + "を読み込みました");
            }
            bfr.close();

        }catch(IOException e) {
            e.printStackTrace();
        }
    }

}
//結果
java.io.FileNotFoundException: C:\test3.txt (指定されたファイルが見つかりません。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileReader.<init>(FileReader.java:72)
	at SampleProgram.main(SampleProgram.java:12)


//例外を外へ投げる
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class SampleProgram {

    public static void main(String[] args) throws IOException {

        File file = new File("C:\\test3.txt");
        FileReader fr = new FileReader(file);
        BufferedReader bfr = new BufferedReader(fr);
        String ss = null;

        while((ss = bfr.readLine()) != null) {
            System.out.println(ss + "を読み込みました");
        }
        bfr.close();

    }

}
//結果
Exception in thread "main" java.io.FileNotFoundException: C:\test3.txt (指定されたファイルが見つかりません。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileReader.<init>(FileReader.java:72)
	at SampleProgram.main(SampleProgram.java:11)
```

## 自分で例外を作る

### 既存のクラスを使う

throwで投げられるのは、Throwableを継承したクラスのインスタンス。

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

public class SampleProgram {

    public static void main(String[] args) throws IOException {

        try {
            File file = new File("C:\\test3.txt");
            FileReader fr = new FileReader(file);
            BufferedReader bfr = new BufferedReader(fr);
            String ss = null;

            while((ss = bfr.readLine()) != null) {
                System.out.println(ss + "を読み込みました");
            }
            bfr.close();
        }catch(IOException e) {
            IOException ee = new IOException("IOExceptionが発生！！");
            throw ee;

        }

    }

}

//結果
Exception in thread "main" java.io.IOException: IOExceptionが発生！！
	at SampleProgram.main(SampleProgram.java:21)

```

### 自作する
用意されていない例外を自分で作成する場合は、Exceptionクラスを継承する例外クラスを作る。

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


class myException extends Exception{
    myException(String msg) {
        super(msg);
    }

}

public class SampleProgram {

    public static void main(String[] args) throws Exception {

        try {
            File file = new File("C:\\test3.txt");
            FileReader fr = new FileReader(file);
            BufferedReader bfr = new BufferedReader(fr);
            String ss = null;

            while((ss = bfr.readLine()) != null) {
                System.out.println(ss + "を読み込みました");
            }
            bfr.close();
        }catch(Exception e) {
            e.printStackTrace();
            throw new myException("thorwしました");

        }

    }

}

// 結果
java.io.FileNotFoundException: C:\test3.txt (指定されたファイルが見つかりません。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileReader.<init>(FileReader.java:72)
	at SampleProgram.main(SampleProgram.java:19)
Exception in thread "main" myException: thorwしました
	at SampleProgram.main(SampleProgram.java:29)


```

# コンストラクタ

## 基本

```java
アクセス修飾子 クラス名 (引数型 引数) {
// なにか処理
}
```

## 継承関係のある場合
コンストラクタは継承されない。

```
//親クラス
class p{
    p(){
        System.out.println("親のコンストラクタ１");
    }
    p(int x){
        System.out.println("親のコンストラクタ２");
    }
}
//子クラス
class c extends p{

}

public class SampleProgram {
    public static void main(String[] args) throws Exception {
        c cc = new c(10); 
        c cc = new c();
    }
}
```

```
c cc = new c(10);
````

なら
「コンストラクターc(int)は未定義です」のコンパイルエラー

```
c cc = new c();
```
で
「親のコンストラクタ１」が表示される
親のコンストラクタ(引数なし)が継承されているかに見せかけて
子クラスになにも宣言されてないので、コンパイラによって自動的にデフォルトコンストラクタが追加されたらしい。

ソース上ではわからないがこんな感じで、親のコンストラクタを呼ぶようになっているらしい

```
class c extends p{
  c(){
    super();
  }
}
```

## 親と子はセット？？
子に明示的にコンストラクタを追加してみたが、なぜか親のコンストラクタも呼ばれた。

```
class p{
    p(){
        System.out.println("親のコンストラクタ１");
    }
    p(int x){
        System.out.println("親のコンストラクタ２");
    }
}

class c extends p{
    c(){
        System.out.println("子のコンストラクタ１");
    }
}

public class SampleProgram {

    public static void main(String[] args) throws Exception {

        c cc = new c();

    }

}

// 結果
親のコンストラクタ１
子のコンストラクタ１
```

結局、子クラスのインスタンスが生成されたときに、もちろん、子クラスのコンストラクタが実行される。が、それより先に親クラスの引数なしのコンストラクタを勝手に呼ぶらしい。
ソース上では見えないが、こういうことらしい。

```
class c extends p{
    c(){
        super();★コンパイラによって勝手に付けられる
        System.out.println("子のコンストラクタ１");
    }
}
```

むむ。。。知らないとはまりそう。。

# その他
## スニペット（snippet）
丸暗記したりコピペで流用できる構文のこと

## System.out.printlnを少しでも省略したい・・


```java

import static java.lang.System.*;

public class SampleProgram{
    public static void main(String[] args) {
        out.println("hoge");
    }
}
```

# 参考になるリンク
[ひしだま's 技術メモページ](http://www.ne.jp/asahi/hishidama/home/tech/index.html)
→[Java](http://www.ne.jp/asahi/hishidama/home/tech/java/index.html)