ざっくりJava～変数、文字列操作、ログ～

#目次
<a href="#hensuu">１．変数と型</a>
1.1　型変換（キャスト）のやりかた
1.2　配列の書き方
1.3　列挙型で自由に型を作る
1.4　参照変数
<a href="#string">２．文字列をいろいろする</a>
2.1　調査する系
2.2　検索する系　
2.3　切り出す系
2.4　変換する系
2.5　文字列の連結
2.6　文字列操作での注意点
2.8　正規表現
2.9　書式を整形する（printf）
<a href="collection">３．配列っぽいコレクション</a>
3.1　ArrayList
3.2　HashSet
3.3　HashMap
3.4　総称型（Generics）
<a href="#log">４．ログ</a>
4.1　ライブラリ
4.2　重要度
4.3　ログ出力の方法
<a href="#etc">５．その他</a>
5.1　OSに依存しない改行コードの記述方法
5.2　日時の操作

#<a name="hensuu">変数と型</a>

##型変換（キャスト）のやりかた

```java
//int型をString型にする
int i;
String s = Integer.toString (i);

//String型をint型にする★
String s;
int i = Integer.parseInt (s);
```
 

##配列の書き方

```java
int hako[] = new int[5];
インスタンス変数.hako = new int[]{12,3,35}
```

##列挙型で自由に型を作る
この値しか入れられないようにしたいという時に自分で型を作ってしまう。（人為的ミスもなくなる）

```java
enum AccountType{FUTSU,TOZA,TEIKI;} //　⬅　enum　型名（値、値、、、;）として定義する
public class Account{
    private String accountNo;
    private int balance;
    private AccountType accountType;
    public Account(String aNo,AccountType aType){ //　⬅　引数としても使えるようになるので間違った値が入らなくなる。
    .....
}
```

※ `import static AccountType.*;` とやれば、いちいちnewする時に引数にAccountTypeと入れる必要がなくなる！！


##参照変数

クラス型、配列型、インターフェース型の３つを参照型という。これらの方の変数を参照変数という。


#<a name="string">文字列をいろいろする</a>

##文字列を調査する系

```java
Sgring s1 = "テストJava"; 
String s2 = "Java";
if(s2.equals(s3)){ //　⬅　等しいかどうか
    System.out.rintln("等しい")
}
if(s2.equalsIgnoreCase(s3)){ //　⬅　大文字小文字区別せずに等しいかどうか
     System.out.rintln("等しい")
}
int ln = s1.lingth(); //　⬅　長さがどれくらいか
if(s1.isEmpty()){ //　⬅　中身が空かどうか。空ならtrueを返す
    System.out.rintln("空です") 
}
```
 

##文字列を検索する系

```java
String s1 = "Java and JavaScript";
if(s1.contains("Java")){ //　⬅　指定の文字が文字列に含まれてるか
　System.out.println("入ってます");
}
if(s1.startsWith("Java")){ // ⬅　先頭が指定文字で始まってるか
    System.out.println("Javaで始まってます");
}
if(s1.endsWith("Script")){ //　⬅　末尾が指定文字で終わってるか
    System.out.println("Javaで終わってます");
}
int nb1 = s1.indexOf("Java"); // ⬅　指定の文字が先頭から検索していって先頭から何文字目にあるか
int nb2 = s1.lasIndexOf("Java"); // ⬅　指定の文字が最後尾から検索していって先頭から何文字目にあるか
```
 
##文字列を切り出す系

```java
String s1 = "Java Programing";
System.out.println("３番目の文字は"+s1.charAt(3)); // ⬅　指定位置の１文字を取り出す
s1.substring(3,2); //　➡　指定位置から指定位置までの文字列を取り出す
```
     

##文字列を変換する系

```java
String s1 = "Java ";
s1.toLowerCase(s1); // ⬅　大文字を小文字に変換する
s1.toUpperCase(s1); //　⬅　小文字を大文字に変換する
s1.trim(s1); //　⬅　先頭か末尾にある余計な空白やタブを削除する。※全角スペースは除去されない！！
s1.replace("a","X"); //　⬅　指定文字を指定文字へ変換する
```
 
##文字列の連結
連続で連結させるなら、＋演算子を使うよりも、StringBuilderを使った方が処理速度が圧倒的に早い。
String変数に入れたものは基本、中身が変更できない。
＋演算子を使うと繋げた文字列をわざわざnewして新しいインスタンスを作ってその中に入れている。StringBuilderはnewせずに中身変更出来るので早い。

```java
StringBuilder sb = new StringBuilder();
for(int i =0; i<10000 ; i++){
    sb.append("Java"); //　⬅　文字をどんどん連結させる
}
String s = sb.toString(); //　⬅　連結した文字列を取り出す
```
※Java1.4以前のバージョンを使ってたり、複数スレッド使ってるとBuilder使えないので、同じようなStringBufferというクラスを使う。（appendなど、使い方は全く同じ）

##文字列操作での注意点

###オブジェクトの使い回し
String型変数に文字列リテラルを代入して初期化する場合、同じ文字列だとオブジェクトを使いまわす。

```
String s1,s2;
s1 = "sample";
s2 = "sample"; //s1とs2は同じオブジェクトを参照している

String s3,s4;
s3 = "sample";
s4 = new String("sample"); //newすると別のオブジェクトになる。
```

###オブジェクトの生成
String型は一度初期化されると、中身の値を変更できない。
代入しているように見えるのは、新たなオブジェクトを作ってその参照を代入しているから。
古いオブジェクトは誰からも参照されなくなるのでGCで破棄される。

```
String s1;
s1 = "sample";
s1 = "test"; //testのオブジェクトが作られ、s1にそのオブジェクトの参照が代入される
```

##正規表現

```java
String name = "D208A20N";
if(name.matches("[A-Z][A-Z0-9]{7}")){ //　⬅　trueとfalseで返してくる
    System.out.println("合ってます");
}
```

###正規表現のいろいろ

```
 {n}　　直前文字がn回繰り返されてること
{n,}　　直前文字がn回以上繰り返されてること
{n,m}　直前文字がn回〜m回の間で繰り返されてること
?　　　直前文字が0回または1回繰り返されてること
+　　　直前文字が１回以上繰り返されてること
.　　　 何でもいいので１文字あること
*　　　直前文字が何回でもいいから繰り返されてること
.*　　　どんな文字でも長さでもOK
[]　　　その中にある文字のどれかに当てはまること
```

例）　[LIN]　　LかIかNのどれかに当てはまること
[A-Z]　　大文字AからZのどれかに当てはまること

```
¥d　　いずれかの数字（[0-9]とおなじ）
¥w　　英字・数字・アンダーバーのどれか（[a-zA-Z_0-9]と同じ）
¥s　　空白であること（スペース、タブ、改行など）
```
 

##書式を整形する
printfを使う

```java
System.out.printf("%8s %6s 所持金%,5d",kimrion,human,32000); // ⬅　書式を指定して表示
```
「kimrion   human 所持金 32,000」と表示される

 「%　修飾　桁　型」で設定する。

```
•修飾
•「,」・・・３桁ごとにカンマ入れる　
•「0」・・・空き領域を０で埋める
•「-」・・・左寄せ（数字）
•「+」・・・符号を表示する
•桁　・・・「n.m」だと小数点も表示
•型
•「d」・・・整数
•「s」・・・文字列
•「f」・・・小数
•「b」・・・真偽
```
 
#<a name="collection">配列っぽいコレクション</a>
コレクションは配列の進化版的なもの。
正式にはコレクションフレームワークという。

コレクションは３種類

```
・リスト　配列っぽいもの
・マップ　連想配列っぽいもの
・集合　同じデータは入れられないもの
```
※コレクションではすべてのオブジェクトを一度Objectインスタンスにキャスト（型変換。ある型の値を別の型に変換すること）して保管するようにしている
※コレクションの中にはint型やdouble型などの基本型の値は入れられない！！ラッパークラスを使って、ボクシングが必要！！

使うライブラリ：`import java.util.*;`

##リストの基本は「ArrayList」クラス
リストに格納しているインスタンスは「参照先」を格納しているので注意。

```java
ArrayList sample = new ArrayList();

//オブジェクトの追加
sample.add(10);
sample.add(2,"テスト"); // ⬅　指定番号の配列に挿入する

//オブジェクトの取り出し
Object obj = sample.get(2); // ⬅　配列番号を指定
 
//オブジェクトの変更
Object obj = sample.set(2, "更新"); //　⬅　指定番号の配列の値を変更

//オブジェクトの削除
obj.remove(2);　// ⬅　指定番号の配列を削除
obj.remove("オブジェクト"); //　⬅　配列の値が○○なものを削除

//※削除すると後ろの配列を前に自動で詰めてくれる！！（削除された空の配列が残るわけじゃない）
//※あくまで「ArrayListから取り除く」ものであって、オブジェクトそのものを消してしまうわけではない

//保管している要素の数を得る
int a = sample.size();
```

※他にも「LinkedList」というものもある！！それぞれ得意不得意がある。
ArrayListは挿入削除が不得意！（挿入削除した以降の配列をコピペしてスライドする必要があるから）
LinkedListは数珠方式なので、挿入削除したらその前の配列に次の配列はこっちだよと教えてあげればいい。
でも、配列番号がないので、何番目の配列を取得したい時には先頭からいちいち数えないといけない！！

 
##HashSetという集合

「Set」というインターフェイスを実装したクラスとして用意されている。※集合にインデックス番号はない！！

その値が集合に含まれてるかどうか。ある集合に合致する値を取得。するためだけのも！！

```java:使い方
HashSet sample = new HashSet();
 
//オブジェクトの追加/削除
sample.add(10); //　⬅　既に同じ値がある場合でもエラー出ないで無視される
boolean flag = sample.remove("サんプル");
//※取り除く値が含まれていた場合はtrueが、いなければfalseが返される。なくてもエラーにはならない。

//値が集合に含まれているか調べる
boolean flag = sample.contains( 20 );
 

//含まれている値の数を返す
int a = sample.size();
 

//全要素を配列として取り出す
Object[] obj = sample.toArray();
 

//順番に要素を取り出す
for(Object obj : set){
            System.out.println(obj);
}
//※配列番号で管理していないので、取り出される順番は分からない。順番は毎回違う。
```
 
※同じようなので、値を格納した順序で並べる「LinkedHashSet」や指定クラスの順序で並ぶ「TreeSet」というものもある。
 

##HashMapというマップ
「キー」と呼ばれる名前と値が組になっている。この組のことを「エントリー（Entry）」という。

```java:使い方
Map sample = new HashMap(); //　⬅Mapクラス型でインスタンス化した方が良い

//値の追加
sample.put( "神奈川県" , "横浜市" ); //　⬅　キーと値で格納

//値の取得/削除
Object obj = sample.get(10);
sample.reove( 10 );

//保管されている全値を得る
Collection[] c = sample.values();

//保管されている全キーを得る
Set s = sample.keySet();

//Map.EntryのSetを得る
Set s = sample.entrySet();

//要素数を得る
int i = sample.size();
```

```java:例
public static void main(String[] args) {
        Map map = new HashMap();
        map.put("国語", 98);
        map.put("算数", 79);
        map.put("理科", 65);
        map.put("社会", 82);
        for(Object obj : map.entrySet()){
            Map.Entry entry = (Map.Entry)obj;
            System.out.println(entry.getKey() + ": " + entry.getValue());
}
```

##総称型（Generics）
コレクションにはなんでも入れてしまえるため、不意に変な物を入れてしまわないように
ある型しか入れられない様制限をかけられるもの。
例えば、「Stringしか入れられないArrayList」であれば、こんな具合に作成。

```java
ArrayList<String> sample = new ArrayList<String>();
//Java7からはこっちでOK　➡　ArrayList<String> sample = new ArrayList<>();
```

HashSetでも、同じように使うことができる。
HashMapの場合には、キーと値の両方に使用する型を設定することができる。

```java
HashMap<String,Integer> sample = new HashMap<String,Integer>();
```

※総称型を使うと、Objectではなく、直接Stringとしてとり出すことができる。キャスト必要なし。


<a name="log">#ログ</a>
##色々なライブラリ
ログ出力するライブラリは色々ある。
「Log4J」「java.util.logging」「commons-logging」「SLF4J」など。
どれも基本的な機能は

・メソッドを呼び出して、文字列をログファイルなどに出力する
・ログ出力時に重要度を指定できる

もの。
##重要度
ライブラリによって、５〜８段階くらいに分かれている。
「Log4J」「commons-logging」「SLF4J」なら重要度が高い順から

```
FATAL
ERROR
WARN
INFO
DEBUG
TRACE
```

##ログ出力の仕方

```java:commons-loggingの場合
import org.apache.commons.logging.*;
public class Sample{
   public static void main(String[] args){
      Log logger = LogFactory.getLog(Main.class);
      if(args.length != 2){
        logger.error("起動引数の数が以上です："+args.length);
      }
   }
}
```

※実務では、アプリケーション作成後に運用・保守担当がログ監視し、「WARNが出たら警報を鳴らす」「ERRORが出たらメールで通知」などとログレベルごとに決めていくので、ログレベルの使いどころをきちんと決めないとメールが来まくる事態になるので注意。

#<a name="etc">その他</a>

##どのOSにも対応した改行コードを記述する

```java
final String BR = System.getProperty("line.separator");
System.out.println("改行します"+BR+"改行しました");
```

##日付の操作

###日付を表示する

```java
import java.util.*;
import java.text.*;

Date date = new Date(); //今日の日付を得る

//case1:日付を表示する
DateFormat df = DateFormat.getInstance(); 
System.out.println(df.format(date));

//case2:自由に編集して表示する
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh時mm分ss秒");
System.out.println(sdf.format(date));

//case3:ロケールを使用して、ある国の日時を表示する
Locale america = new Locale("en","US"); //引数はISO言語コードとISO国コード
DateFormat df1 = DateFormat.getDateInstance(DateFormat.DEFAULT,america);
System.out.println(df1.format(date));
```

###日付を計算する
DateオブジェクトをCalendarオブジェクトに移して、日付計算や年月日を取得できる。

```java
import java.text.*;
import java.util.*;

//カレンダー作成
Calendar c = Calendar.getInstance(); 
Date date = new Date();
c.setTime(date);

//表示するためのフォーマット生成
DateFormat df = DateFormat.getInstance();

//日付の計算
c.add(Calendar.MONTH, 1); //１か月後を計算
c.add(Calendar.DATE, 10); //さらに10日後を計算
c.add(Calendar.DATE, -3); //そこから3日前を計算
Date date2 = c.getTime();
System.out.println(df.format(date2));

//日時をセットしてカレンダー作成
c.set(2015, 2, 15, 12, 10); //「年、月、日、時、分」の順。月だけは0から始まる。（この場合は３月）
Date date3 = c.getTime();

//カレンダーから要素を取り出す
System.out.println("年は"+c.get(Calendar.YEAR)); //年を取り出す
System.out.println("月は"+c.get(Calendar.MONTH));　//月を取り出す

```