Java学習ノート_140713（例外処理）

# 例外処理（続き）

Exceptionクラスを使用することもできるが基本的には個別の例外処理を行う（どういう例外かわからないとあまり意味が無い）。

```java
try{
//...
}catch(NumberFormatException e){
//...
}finally{
//必ず実行される
}
```

## 例外クラスのメソッド

* public 例外クラス名() : 引数なしのコンストラクタ
* public 例外クラス名（String message) : メッセージ文字列を引数にもつコンストラクタ
* public void printStackTrace() : スタックトレースを表示する
* public String getMessage() : メッセージ文字列を取得する


```java
try{

}catch(Exception e){
	e.printStackTrace();
	//こういう書き方でも出力される
	System.out.println(e);
}

```

## 例外は食べ物ではない

例外をキャッチしておきながら、**何もしないことは絶対にしてはいけない。**

## 例外のスロー

```java:ThrowError.java
public class ThrowError {
	public static void main(String[] args) {
		int result = divOneTwo(args);
		System.out.println("result : " + result);
	}
	static int divOneTwo(String[] args){
		if(args.length < 2){
			IllegalArgumentException e = new IllegalArgumentException("引数は2つ指定してください。");
			throw e;
			//こう記述もできる
			throw new IllegalArgumentException("引数は2つ指定してください。");
		}
		return Integer.parseInt(args[0]) / Integer.parseInt(args[1]);
	}
}
```
## チェック例外と非チェック例外

 * チェック例外 : 必ずチェックするべき例外 / java.lang.InterruptedException, java.io.IOException
 * 非チェック例外 : どこでも発生する可能性がある例外 / java.lang.NullPointerException, java.lang.IndexOutOfBoundsException

**チェック例外は、必ず例外がスローされた場合の処理を記述する必要がある。**

具体的には、

1. 例外をtry{...}catch{...}でキャッチする
2. throw宣言をする（メソッドの呼び出し側に処理を任せる）

のいずれかの処理を行う。

```java:ThreadSample.java
public class ThreadSample {
	public static void main(String[] args) {
		System.out.println("処理開始");
		sleep2s();
		System.out.println("処理終了");

	}
	static void sleep2s(){
		try{
			Thread.sleep(2000);
			
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
}
```

```java:ThreadSample2.java
public class ThreadSample2 {
	public static void main(String[] args) throws InterruptedException {
		System.out.println("処理開始");
		sleep2s();
		System.out.println("処理終了");

	}
	static void sleep2s() throws InterruptedException{
			Thread.sleep(2000);
	}
}
```
Eclipseでは例外処理を書かないとエラー表示され、該当箇所をクリックすると、try{}catch{}かthrowを宣言するか選べる。便利。

## ログ

大規模なアプリケーションの場合、エラーやスタックトレースはログファイルに出力する。java.util.logging、もしくはLog4Jというライブラリを利用するケースが多い。

問題は読書時にやったので割愛。

# コンソール出入力

Scannerクラスを利用する。先にやっていたが、主なコンストラクタとメソッドをまとめる。

名前 | 説明
----|----
Scanner (InputStream source) | コンストラクタ(InputStreamが引数）
Scanner (File source) | コンストラクタ(Fileが引数）
Scanner (String source) | コンストラクタ(Stringが引数）
public Scanner useDelimiter(String pattern) | 区切り文字を指定、引数には正規表現のパターンを記述可能
public String next() | 次のトークンを返す
public boolean hasNext() | 次のトークンが存在するかを真偽値で返す
public String nextLine() | 次の行までの文字列を読み込みます
public boolean hasNextLine() | 次の行が存在するかを真偽値で返す
public int nextInt() | 次のトークンをint型にして返す
public boolean hasNextInt() | 次のトークンが存在して、int型で在る場合の真偽値を返す
public double nextDouble() | 次のトークンをdouble型にして返す
public boolean hasNextDouble() | 次のトークンが存在して、double型で在る場合の真偽値を返す

```java:ScannerSample.java
import java.util.Scanner;

public class ScannerSample {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("何か入力してください。");
		if(sc.hasNextDouble()){
			double d = sc.nextDouble();
			System.out.println("入力された数値 : " + d);
			
		}
		else if(sc.hasNextInt()){
			int i = sc.nextInt();
			System.out.println("入力された整数 : " + i);
			
		}
		else if(sc.hasNext()){
			String str = sc.next();
			System.out.println("入力された文字 : " + str);
		}
		
	}

}
```

この場合、double型で出力されるか、文字列で出力されるかになる。

```java:MultipleInputSample.java
import java.util.Scanner;

public class MultipleInputSample {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("何か繰り返し入力してください。");
		while(sc.hasNext()){
			String s = sc.next();
			System.out.println("入力された文字 : " + s);
		}
	}
}
```

ScannerクラスはJava5で導入されたクラスなので、Java 1.4以前は利用できない。代わりにInputStreamReader,BufferedReaderクラスを利用する。またキーボード入力があるのでIOExceptionクラスをインポートする。

## 書式つき出力

Java5以降はprintfメソッドを使うことで、桁数指定や右寄せといった書式を指定した表示を簡単に行うことが出来る。変換文字は以下の表のものが指定できる。C言語のprintfに依拠。

### 変換文字

変換文字 | 説明
----- | -----
o | 8進数の整数
d | 10進数の整数
x, X | 16進数の整数で出力
f | 10進数の浮動小数点として出力する
s, S | 文字列を表示する。For
c, C | charの引数の1文字を表示する
t, T | 日付と時刻出力用のプレフィックス。%tm, %tdのような形で変換タイプを指定する
n | OS固有の改行文字を出力する
% | %文字(¥u0025)を出力する。%自体を表示したい場合は、%%と記述する


### 幅と精度

```java
System.out.printf("num[%5d]%n",12);  // num[   12]
System.out.printf("num[%5.1f]%n",12.3);  // num[ 12.3]
```

### フラグ
フラグで細かい表示形式を指定できる。

変換文字 | 説明
----- | -----
'-' | 左揃え
'#' | 代替フォームを使用
'+' | 先頭に+か-を必ずつける
' ' | +の場合空白を先頭につける
',' | ロケール特有のグループ区切り文字を付ける。
'(' | 負の数値を括弧で囲む
'0' | 数字の左側を0でパディングする（0フィル）

## 可変長引数

配列ではない、複数の引数を渡したい場合は、可変長引数の構文を使う。一つのメソッドに定義できる可変長引数は1つだけ、他の引数と定義する場合は、最後の引数を可変長引数にする。


```java:PrintfSample.java
public class PrintfSample {
	public static void main(String[] args) {

		//フラグサンプル。num[]%nの形式は、わかりやすくするために含めている
		System.out.printf("num[%5d]%n",12);			//	num[   12]
		System.out.printf("num[%5.1f]%n",12.3);		//	num[ 12.3]
		System.out.printf("num[%-5d]%n",12);		//	num[12   ]
		System.out.printf("num[%05d]%n",12);		//	num[00012]
		System.out.printf("num[%+5d]%n",12);		//	num[  +12]
		System.out.printf("num[%(5d]%n",-12);		//	num[ (12)]
		System.out.printf("num[%,5d]%n",1234568789);		//	num[1,234,568,789]
		System.out.printf("num[%#x]%n",0x12);		//	num[0x12
		
		//複数の引数と、引数番号のサンプル
		//引数順序を変更したい場合は、引数の番号+$をつけて指定する(1$,2$,....,n$)
		
		System.out.printf("num1=%d,num2=%d%n",10,20);
		System.out.printf("num1=%2$d,num2=%1$d%n",10,20);
		
		//可変長変数メソッド呼び出しサンプル
		listName("hoge","fuga","foo","bar");
		

	}
	//可変長変数のメソッド定義サンプル
	static void listName(String... strs){
		for(String str : strs){
			System.out.println(str);
		}
	
	}
}

```