星期三, 10月 31, 2012

OCPJP Day 13


*系統參數(System Properties)
  • 類似作業系統環境變數的概念, 可以算是JVM的環境變數
  • 透過System.getProperties方法可以回傳一個Properties的物件
  • 透過System.getProperty方法回傳一個代表某一命名property對應的字串值
  • 透過 -D 還可以新增新的property

*Properties 類別
  • Properties類別實作了property名稱和property值之前的對應關係(String to String)
  • propertyNames方法回傳一個包含所有property名稱的Enumeration物件
  • getProperty方法回傳一個代表某一個命名property的對應字串.


Notes:
  • Enumeration TS(Thread-safe), Iterator NTS(Non-Thread-safe)
  • Enumeration 會在指標上下各放一個指標(Before the first)(After the last) 來配合 hasMoreElements 以及 nextElement. 也就是如果有10個記憶體指標, 會有12個位置.


PropertiesDemo.java

package mod14;

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

public class PropertiesDemo {

public static void main(String[] args) {
Properties props = System.getProperties();
//下面那個Enumeration 以及 while 迴圈來取得properties, 也可以透過 props.list這個API來達成
props.list(System.out);
//分隔符號以下是用 Enumeration 以及 while 迴圈來取得properties
System.out.println("#########################################");

Enumeration propNames = props.propertyNames();
//
while (propNames.hasMoreElements()) {
String propName = (String) propNames.nextElement();
System.out.println("-------------------------------");
String property = props.getProperty(propName);
System.out.println("Property : " + propName + " is " + property + "");
}
}
}


Lab:

Lottery.java

package lab14;

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

public class Lottery {

public static void main(String[] args) {
//如果要排序就使用TreeSet(), 不排序就使用 HashSet()
Set<Integer> numbers = new HashSet();
int random;
while (numbers.size() != 6){
random = (int) Math.ceil(Math.random()*49);
numbers.add(random);
}
System.out.println(numbers);
}
}


*Chapter 12 Exception Assertion
  • Exception
    • Exception是被動的,用來表示一些非預期的情況.
    • 執行時期才會發生.
    • Exception都是類別, 而且每一個套件中均有各自Exception類別.
    • 使用者回報bug的時候常用Exception.
  • Assertion
    • Assertion是主動的
    • 當程式時好時壞的時候, 會使用Assertion

*Exception架構與分類

Throwable
  • Error: 硬體錯誤, JVM錯誤 (嚴重型的錯誤, 不處理)(Unchecked Exception)
  • Exception
    • Runtime Exception: 邏輯上的錯誤(Unchecked Exception 編譯器無法檢查)
      • 80%通常代表程式有瑕疵, 語法上無法處理
      • 20%User Error, 考慮處理他
    • Checked Exception
      • Checked 代表編譯器會檢查
      • 在語法上面一定要處理
        • try-catch
        • throw / throws


AddArguments.java

package mod12;

public class AddArguments {

public static void main(String[] args) {
//
int sum = 0;
for (String s : args) {
sum += Integer.parseInt(s);
}
//
System.out.println("Sum= " + sum);
System.out.println("Thannks you !! Bye!!");
}
}

於外部執行此 java 程式例如(執行命令時位於執行檔案頂層目錄)
java mod12/AddArguments 1 2 3

輸出結果為
Sum= 6
Thannks you !! Bye!!


Notes:
  • 如果有使用 try-catch, 程式會繼續運作下去, 不是直接中斷

Lab: try-catch

AddArguments.java

package mod12;

public class AddArguments {

public static void main(String[] args) {
//
try {
int sum = 0;
for (String s : args) {
sum += Integer.parseInt(s);
}
//
System.out.println("Sum= " + sum);
} catch (NumberFormatException numberFormatException) {
// Report to User 回報使用者輸出的字串
System.out.println("There might be some mistakes with your input.");
}
System.out.println("Thannks you !! Bye!!");
}
}


如果只針對該行程式進行 try-catch

AddArguments.java

package mod12;

public class AddArguments {

public static void main(String[] args) {
//
int sum = 0;
for (String s : args) {
try {
sum += Integer.parseInt(s);
} catch (NumberFormatException numberFormatException) {
System.out.println("Input[ "+s+" ]not correct, So we don't add it!");
}
}
//
System.out.println("Sum= " + sum);
System.out.println("Thannks you !! Bye!!");
}
}


這樣既使輸入的參數有誤, 正確的參數也會加總
例如
java mod12/AddArguments 1 2 3 for 2

輸出結果

Input[ for ]not correct, So we don't add it!
Sum= 8
Thannks you !! Bye!!

Notes:
  • try-catch 陳述式可以多個catch 子句
    • 如果Excepton 沒有繼承關係,
      • catch順序可以隨便排
    • 如果Exception 有繼承關係( java 會使用 instance of 來詢問)
      • catch 必須先catch 子類別, catch 上層的父類別(不然詢問父類別 instance of 一定會回傳 true, 就不會執行下面的catct)
      • 最後會去catch Exception 類別(因為他是所有Exception的父類別)
Exception (有父類別與子類別的關係)
  • IOException (Input / Output 出錯有關)
    • FileNotFoundException
    • EOFException
  • HRException (使用者自訂, 通用大分類的Exception)
    • GenReportException(子類別通常比較細微且實際)
    • CalcSalayException


*finallly 子句
  • 保護的機制
  • 無論如何一定會被執行的程式區塊.
  • 開啟串流要確保串流被關閉


Lab: finally

加上 finally

AddArguments.java

package mod12;

public class AddArguments {

public static void main(String[] args) {
//
// try {
int sum = 0;
for (String s : args) {
try {
sum += Integer.parseInt(s);
} catch (NumberFormatException numberFormatException) {
System.out.println("Input[ "+s+" ]not correct, So we don't add it!");
}finally{
System.out.println("Finally exec!");
}
}
//
System.out.println("Sum= " + sum);
// } catch (NumberFormatException numberFormatException) {
// Report to User 回報使用者輸出的字串
// System.out.println("There might be some mistakes with your input.");
//}
System.out.println("Thannks you !! Bye!!");
}
}


執行該程式
java mod12/AddArguments 1 2 3 for 2

輸出結果為

Finally exec!
Finally exec!
Finally exec!
Input[ for ]not correct, So we don't add it!
Finally exec!
Finally exec!
Sum= 8
Thannks you !! Bye!!

上面會看到輸入 5 個參數, 就確定執行5final 的程式


Notes:
  • Call Stack Mechanism
    • Exception 如果一直往上層(呼叫者丟),丟給 main() 再丟給JVM, JVM 會終止這個程式, 這個稱為Call Stack Mechanism
假如 Exception 的架構如下
Exception ← AException ← BException ←CException

程式如下

public void test(){

try{
1
2
3
4
}catch(BException e){
A
}finally{
B
}
C
}

Case 1 如果程式沒有發生任何Exception
1 → 2 → 3 → 4 → A → B → C

Case 2 如果程式在 3 發生BException
1 → 2 → 3 → 4 → A → B → C

Case 3 如果程式在3發生RuntimeException
1 → 2 → 3 → B → Call Stack Mechanism

Case 4 基於Case 2 但是catch A的程式碼內有 return; catch 區塊
1 → 2 → 3 → A → B → return


Notes:
  • 不管如何, finally都會執行


*常見的例外狀況
  • NullpointException
  • NumberFormatException
  • ArithmeticException
    • 分子與分母都是整數, 然後除以0

*例外處理或宣告的規則
  • 處理
    • 使用try-catch-finally區塊來處理
  • 宣告
    • 透過throws子句來宣告程式(往外面丟)(一定是屬於Checked Exception)

關鍵字有三個是動詞加上s (3人稱)
  • extends
  • implements
  • throws


public class Parent{
//這邊的 throws 有加上s
public void work() throws BException{
//狀況1 if ( … ) { throw new BException(); } //這邊throw沒有加上 s, 命令式, 祈使句
//方法本身即為丟出BException的源頭

//狀況2 ( new Staffing()).doStaff();
// 方法內部去呼叫會丟出BExceptionAPI但是並未使用try-catch來加以處理

}
}

public class Staffing{
public void doStaff()
throws BException{
}
}

Notes:
  • 所以如果方法本身是處理throw的源頭就不會加上s, 反之如果是呼叫別的API就會加上s

星期一, 10月 29, 2012

OCPJP Day 12



  • Map <<interface>> (Key-value 的配對) 沒有順序(不記住加進來的順序)
    • Hashtable(Thread-safe)
      • Properties (Key-value 都是String)
    • HashMap(Non-Thread-safe)
    • LinkedHashMap(順序)(會記住加進來的順序)
    • SortedMap <<interface>>
      • TreeMap

Notes:
  • Map 是使用Key-Value 儲存


HashMapDemo.java

package mod14;

import java.util.*;

public class HashMapDemo{
public static void main(String[] args){
Map<Integer,String> fruits = new HashMap<Integer,String>();
fruits.put(2,"Lemon");
fruits.put(4,"Watermelon");
fruits.put(1,"Pineapple");
fruits.put(5,"Cherry");
fruits.put(3,"Strawbarry");
//HashMap是不排序的如果是整數可能只是恰巧
System.out.println(fruits);
}
}


LinkedHashMap.java

package mod14;

import java.util.*;
public class LinkedHashMapDemo{
public static void main(String[] args){
Map<Integer,String> fruits = new LinkedHashMap<Integer,String>();
fruits.put(2,"Lemon");
fruits.put(4,"Watermelon");
fruits.put(1,"Pineapple");
fruits.put(5,"Cherry");
fruits.put(3,"Strawbarry");
//LinkedHaskMap 會記住放進來的順序,但是不會排序
System.out.println(fruits);
}
}
TreeMap.java

package mod14;

import java.util.*;
public class TreeMapDemo{
public static void main(String[] args){
TreeMap<Integer,String> fruits = new TreeMap<Integer,String>();
fruits.put(2,"Lemon");
fruits.put(4,"Watermelon");
fruits.put(1,"Pineapple");
fruits.put(5,"Cherry");
fruits.put(3,"Strawbarry");
//TreeMap 會排序
System.out.println(fruits);
}
}

*陣列或List的排序
  • 陣列排序用Arrays.sort();
  • List排序用Collections.sort();
  • 加入的元素一定要是Comparable (必須實作Comparable這個interface)
  • 自訂排序java.util.Comparator

public void getSorted(Set s){
//Set 要排序的方法
//方法1. 建立一個 TreeSet , 然後將Set 傳入 (因為只有TreeSet 會排序)
TreeSet ts = new TreeSet(s);
//方法2. 建立一個 ArrayList 然後將Set 傳入
ArrayList al = new ArrayList(s);
Collections.sort(al);

}


Lab:

User.java

package lab14;

// implements Comparable 來排序, 排序的方式1
public class User implements Comparable<User> {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return "<"+firstName+" "+lastName+">";
}
public int compareTo(User arg0) {
//if return value is 0, equal
return firstName.compareTo(arg0.getFirstName());
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((firstName == null) ? 0 : firstName.hashCode());
result = PRIME * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final User other = (User) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}

}

SortByLastName.java

package lab14;
import java.util.Comparator;
// 除了上面的實作Comparable以外,另外一種方法就是實作Comparator
public class SortByLastName implements Comparator<User> {

public int compare(User arg0, User arg1) {
return arg0.getLastName().compareTo(arg1.getLastName());
}

}


TestUser.java

package lab14;

import java.util.*;


public class TestUser {

public static void main(String[] args) {
ArrayList<User> users = new ArrayList<User>();
users.add(new User("John","Wang"));
users.add(new User("Richard","Chang"));
users.add(new User("Vivid","Su"));
users.add(new User("Mary","Chou"));
users.add(new User("Nancy","Wu"));
System.out.println(users);
//Sort by First Name
Collections.sort(users);
System.out.println(users);
//Sort by Last Name
Collections.sort(users,new SortByLastName());
System.out.println(users);
}

}

Lab: 承上例如果要以年紀來排序

建立一個依照年紀排序的 Comparator
AgeComparator.java

package lab14;

import java.util.Comparator;

public class AgeComparator implements Comparator<User> {

@Override
public int compare(User o1, User o2) {
//將兩個使用者的年齡相減來return
return o1.getAge()-o2.getAge();
}
}

User.java

package lab14;

// implements Comparable 來排序, 排序的方式1
public class User implements Comparable<User> {

private String firstName;
private String lastName;
//加入 int age 並封裝
private int age;

public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
//加入建構子
public User(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

//修改toString()
@Override
public String toString() {
return "<" + firstName + " " + lastName + this.age+ ">";
}

public int compareTo(User arg0) {
//if return value is 0, equal
return firstName.compareTo(arg0.getFirstName());
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((firstName == null) ? 0 : firstName.hashCode());
result = PRIME * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final User other = (User) obj;
if (firstName == null) {
if (other.firstName != null) {
return false;
}
} else if (!firstName.equals(other.firstName)) {
return false;
}
if (lastName == null) {
if (other.lastName != null) {
return false;
}
} else if (!lastName.equals(other.lastName)) {
return false;
}
return true;
}

/**
* @return the age
*/
public int getAge() {
return age;
}

/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
}

修改TestUser.java 加入年紀
TestUser.java

package lab14;

import java.util.*;

public class TestUser {

public static void main(String[] args) {
ArrayList<User> users = new ArrayList<User>();
users.add(new User("John", "Wang",15));
users.add(new User("Richard", "Chang",30));
users.add(new User("Vivid", "Su",20));
users.add(new User("Mary", "Chou",25));
users.add(new User("Nancy", "Wu",18));
System.out.println(users);
//Sort by First Name
Collections.sort(users);
System.out.println(users);
//Sort by Last Name
Collections.sort(users, new SortByLastName());
System.out.println(users);
//
Collections.sort(users, new AgeComparator());
System.out.println(users);
}
}

Notes:
  • 如果要套用反序age的排序, AgeComparator 方法反過來, 使用 return o2.getAge() - o1.getAge();

先講Chapter 16 巢狀類別

Notes:
  • 只要可以宣告變數就可以宣告巢狀類別
  • 巢狀類別的好處為可以直接存取外部類別的成員

Lab: 巢狀類別

Outer.java

package mod16;

public class Outer {

private int a = 100;
//巢狀類別可以放在可以宣告變數的地方

private class A {

public void test() {
//可以套用四種存取控制
//巢狀類別的好處為可以直接存取外部類別的成員
System.out.println(a);
}
}

//
public void foo() {
int x = 200;
class B {
}
}

public void bar() {
int x = 300;
class B {
//名稱可以跟上面那個一樣 (區域的巢狀類別)
}
}
}


*巢狀類別(Nested Class)簡介
  • 巢狀類別就是將類別定義在另一個類別中, 所以巢狀類別是外圍類別(Enclosing Class)的成員

*內部類別(Inner Class)
  • Non-static的巢狀類別又被稱為內部類別(Inner Class)
    • 建立跟使用的方式跟一般類別沒啥兩樣.
  • 因為內部類別是外圍類別(Enclosing Class)的非靜態成員, 所以
    • 必須先將外圍類別建立成物件
    • 藉由這個物件才能將內部類別建立成物件
  • 內部類別中不得宣告 static Member, 但有一個例外, 內部類別中可以宣告static final變數並給初值.

如果要將這類別開放出來

Outer.java

package mod16;

public class Outer {

private int a = 100;
//巢狀類別可以放在可以宣告變數的地方
//class A 改成 public
public class A {

public void test() {
//可以套用四種存取控制
//巢狀類別的好處為可以直接存取外部類別的成員
System.out.println(a);
}
}

//
public void foo() {
int x = 200;
class B {
}
}

public void bar() {
int x = 300;
class B {
//名稱可以跟上面那個一樣 (區域的巢狀類別)
}
}
}

Mod16.java

package mod16;

public class Mod16 {

public static void main(String[] args) {
//要先建立外圍物件
Outer o = new Outer();
Outer.A x = o.new A();
x.test();
}
}


*靜態巢狀類別(Static Nested Class)
  • 靜態巢狀類別又提升回Top-Level類別
  • 靜態巢狀類別不得參考外圍類別的非靜態成員


Lab:

Outer.java

package mod16;

public class Outer {

private int a = 100;
//巢狀類別可以放在可以宣告變數的地方
//
public class A {

public void test() {
//可以套用四種存取控制
//巢狀類別的好處為可以直接存取外部類別的成員
System.out.println(a);
}
}

//Inner Class
public void mA(){
//
A m = new A();
m.test();
}

public static class StaticA{
// you could call it with // Outer.StaticA.methodA();
public static void methodA(){
System.out.println("methodA()");
}
//沒有static 就要先建立物件
//you could call it with // Outer.StaticA y = new Outer.StaticA();
//y.methodB();
public void methodB(){
System.out.println("methodB()");
}
}
//
public void foo() {
int x = 200;
class B {
}
}

public void bar() {
int x = 300;
class B {
//名稱可以跟上面那個一樣 (區域的巢狀類別)
}
}
}


Mod16.java

package mod16;

public class Mod16 {

public static void main(String[] args) {
//要先建立外圍物件 才能呼叫
Outer o = new Outer();
Outer.A x = o.new A();
x.test();
//因為是靜態巢狀類別, 所以不需先建立外圍類別物件
Outer.StaticA.methodA();
//
Outer.StaticA y = new Outer.StaticA();
y.methodB();

}
}


*區域巢狀類別
  • 區域巢狀類別不得使用所在方法中的區域變數或參數, 除非使用所在方法中的final區域變數
  • 將類別定義在方法中稱為區域類別(Local Class)

*匿名類別(Anonymous Class)
  • new Class(...) 後面直接加上大括號 {….} , 並在大括號中宣告的新類別成員, 這就產生一個匿名類別(Anonymous Class)(把類別命令的工作交給java), 並為這個匿名類別建立物件.
  • 定義在方法中的匿名類別也可以說是一種區域類別, 與區域類別有相同的限制