2010年8月2日 星期一

Framework: Hibernate

Java Hibernate程式的過程中,我們可以粗分四大步驟(1~4) 與二大檔案(5、6),依序是 :

1. Configuration

1.1. 透過 Configuration File (hibernate.cfg.xml) 設定與 Database 連線的方式與設定要匯入哪些 Mapping File。

1.2 (JavaEE 環境) 透過 JNDI Service 來註冊 org.hibernate.SessionFactory 成為 Global 物件。

1.3 (JavaEE 環境) 設定 AP Server 所提供的 Transaction 的功能。

1.4. 透過 org.hibernate.cfg.Configuration 的 configure() mathod 來讀取 Configuration File。

1.5 透過 org.hibernate.cfg.Configuration 的 buildSessionFactory() 來產生 下一步驟要用到的 org.hibernate.SessionFactory

2. SessionFactory

2.1 一個 org.hibernate.SessionFactory 只對應到一個 Database

2.2 必須在程式要使用之前就必須建立好 SessionFactory,因為需要一點時間才能建立,所以最好是在網站或程式初始化時就去建立,至少必須在程式開始接觸 Database 之前就要建立。

2.3 必須放在所有程式都可以取用到地方 ( 有 JNDI 就註冊到 JNDI 中, 如果沒有 JNDI, 且是Web Apps, 也可以註冊在 ServletContext)。

2.4 org.hibernate.SessionFactory 會 catch 執行 Hibernate 所產生的 SQL statement 和 Database 的 metadata。

2.5 org.hibernate.SessionFactory 是 thread-safe 物件,會自己處理 multi-thread。

2.6 透過 org.hibernate.SessionFactoryopenSession() 或是 getSession() 來 產生/取得 下一步驟要用到的 org.hibernate.Session

3. Session:

3.1 org.hibernate.Session 包含了 JDBC 的 Connection object。

3.2 所以可以視為 Hibernate 與 Database 之間溝通的橋樑、過程。

3.3 org.hibernate.Session 可以提供 org.hibernate.Transaction object

3.4 所以存取 Persistent Class 都需要透過 org.hibernate.Session

4. Transaction:

4.1 org.hibernate.Transaction 將真正在底層執行 Transaction service包裝起來,

在 J2EE 中使用 JTA 的 UserTransaction 服務多個 Database (ex: 轉帳);或利用 J2SE 中 JDBC 的 Transaction 來服務一個 Databae。

4.2 在 Hibernate 3.x 中,存取 Persistent Class 的動作一定要包在 org.hibernate.Transaction 的可視範圍之中。

例如:

Transaction transaction = session.beginTransaction();

存取 Persistent Class ...
......

transaction.commit();

5. Persistance Class:

5.1 最好是 JavaBeans 的架構。

5.2 使用 Hibernate 來處理的 Table 一定要有 primary key,且對應到 Java Class 中的 欄位與 setter,為了避免誤改,所以都應該宣告為 private 屬性。primary key 是獨一無二的 id,所以在選定時最好避免與目前專案相關性太高的欄位,應儘量使用流水號。

5.3 不要使用 final。Hibernte 會自動為每個 Persistent Class 產生各自的 proxy,但 proxy 會繼承 Persistent Class,所以一旦設為 final,將會限制 proxy 所提供的功能。

5.4 要小心處理 Persistent Class 的三種狀態:
transient : 尚未跟 Persistent Context 接觸。( 與 Session 沒有關係的狀態 )
persistent : 正在跟 Persistent Context 接觸。
detached : 以前曾經跟 Persistent Context 接觸,但現在分開了。

6. Hibernate Mapping File:

6.1 每一個 Persistent Class 都會有自己的 Mapping File,以維護 Table 與 Persistent Class 的對應關係。

6.2 Mapping File 的副檔名為 .hbm.xml

6.3 Mapping File 的存放位置必須跟所對應的 Persistent Class 的目錄相同。

6.4 在使用 Mapping File 之前必須註冊到 Configuration file 中,通常使用靜態的方法,直接寫入 hibernate.cfg.xml 中。

Singleton

獨體模式 Singleton

確保一個類別只有一個實體,並給它一個存取的全域點(global point)。


有些物件只需要一個實體,如果有多個實體同時存在,反而會造成問題,如 memory pool、garbage collector... 等。

全域物件

最簡單的作法可以採用一個全域物件。但這需要透過程式員之間的約定並嚴格遵守才能達成;並且,這個全域物件在程式開始執行時就建立好了,如果一直都沒用到,反而造成資源無謂地浪費

物件的出生

物件產生 Q&A:

Q: 一個物件如何產生?
A: 對於 C++ 而言,有兩種方式。一種是直接宣告變數式的 Object obj,一種是動態產生 Object* obj = new Object();而對於 Java 而言,只有一種:new Object()。無論哪種方式,都會配置記憶體,然後以 constructor 來初始化物件。

Q: 如何限制人們建立物件?
A: 將 constructors 宣告為 private,如此一來外部無人可以呼叫 constructors。

Q: 那有誰可以建立物件?
A: 物件自己(物件本身的其他方法可以呼叫 constructors)。

Q: 要如何取得一個這樣的物件實體?
A: 物件提供一個方法,稱為 getInstance(),這個方法會初始化一個物件並回傳。

Q: 如果這個實體是一個 static 變數,會怎麼樣?
A: 那所有人都會存取到同一份實體。

獨體模式

獨體模式 Singleton就是可以確保某個類別只有一個實體的方法。將一個類別的 constructors 宣告為 private,並提供一個方法 getInstance() 讓外部取得物件的唯一實體。這個實體是一個 static 物件,若第一次呼叫時這個唯一實體沒有被初始化,則以 private constructor 來為它初始化。如果已經初始化完成了,就直接回傳這個 static 實體。這種在需要時才建立物件的技術,稱為 lazy instantiate

Java 版本程式碼:

JAVA:
  1. public class Singleton
  2. {
  3. private static Singleton uniqueInstance;
  4. private Singleton() {} //private ctor

  5. public static Singleton getInstance() {
  6. if(uniqueInstance == null) {
  7. uniqueInstance = new Singleton();
  8. }
  9. return uniqueInstance;
  10. }
  11. }

C++版本:

C++:
  1. class Singleton
  2. {
  3. Singleton() {} //private ctor

  4. public:
  5. static Singleton& getInstance() {
  6. static Singleton uniqueInstance;
  7. return uniqueInstance;
  8. }
  9. };

這是獨體模式非常簡單的類別圖:
獨體模式

多緒環境的獨體模式

但是上述的獨體模式實踐,在多緒環境下會有 race condition 問題

如 Java 版本第 9 行的判斷式,如果第一個執行緒判定條件成立並進入 if-block,但在產生實體前,就切換到第二個執行緒。則第二個執行緒也會判定條件成立並進入 if-block,造成兩個執行緒各執有一份實體,破壞 Singleton 的唯一性

這種情況在 Java 有三種解決方式。

將 getInstance() 宣告為 synchronized 方法:

JAVA:
  1. public class Singleton
  2. {
  3. private static Singleton uniqueInstance;
  4. private Singleton() {} //private ctor

  5. public static synchoronized Singleton getInstance() { //加上 synchronized 關鍵字
  6. if(uniqueInstance == null) {
  7. uniqueInstance = new Singleton();
  8. }
  9. return uniqueInstance;
  10. }
  11. }

synchronized 關鍵字可以「同步化」一個方法 —— 同時只有一個執行緒可以進入此方法執行。在此執行緒結束之前,其他執行緒只得等待。缺點:每一次呼叫 getInstance() 都得同步化執行(事實上只有第一次需要),效能較差。

「率先」建立實體:

JAVA:
  1. public class Singleton
  2. {
  3. private static Singleton uniqueInstance = new Singleton();

  4. private Singleton() {}

  5. public static Singleton getInstance() {
  6. return uniqueInstance;
  7. }
  8. }

以 static initializer 來建立 uniqueInstance 物件(而不使用 lazy instantiate)。這麼一來 uniqueInstance 在 JVM 載入此類別時就會被建立,無 race condition 問題。缺點:一開始就得建立實體,若不使用則徒然浪費資源

Double-checked lock:

JAVA:
  1. public class Singleton
  2. {
  3. private volatile static Singleton uniqueInstance; //加上 volatile 關鍵字

  4. private Singleton() {}

  5. public static Singleton getInstance() {
  6. if(uniqueInstance == null) { //如果實體不存在,才會進入下面的同步區塊
  7. // ---- synchronized block ---- 同步區塊會 atomic 執行
  8. synchronized(Singleton.class) {
  9. if(uniqueInstance == null) { //再做一次檢查,怕在進入前有其他執行緒趁隙將實體建立
  10. uniqueInstance = new Singleton();
  11. }
  12. }
  13. // ---- synchronized block ----
  14. }
  15. return uniqueInstance;
  16. }
  17. }

volatile 關鍵字 uniqueInstance 宣告為多工處理的共用變數,並以 synchronized block 讓檢查與建立的步驟 atomic 進行。但是加上一個 if 來讓此區塊只有「第一次」才會進入,兼顧了效能。這是效能最好的方案,但較複雜,且 Java 1.4 以前版本不適用



From~http://notes.xamous.net/archives/139

2010年8月1日 星期日

DAO/Repository/Hibernate/JDBC

Repository in Action

10:30上午 二月 17, 2006 in category Java by ingramchen

我朋友最近正在讀 POJOs in Action 這本書。Repository/DAO/Hibernate/JDBC 之間的關係搞的他一頭渾水,下面我嘗試就我所知的,提供一些解釋:

Repository 是 domain 中,有關 儲存 這種觀念的具現。當你在 model domain 時,你會觀察到有些物件在建立完成後,需要被留下來,並且 儲存在某個地方。然後下次要用時再把它取出,然後繼續工作。下面是物件的 life cycle 的流程:

   new object --> object working... --> persistent and store object
--> query stored object --> object continue working --> ....

當你觀察到這些行為後,你可以將這個觀念抽象化,並且設計一個專職的 物件來管理。在 Domain Driven Design 這本書中,作者命名這樣的物件為 Repository 。從上面的流程也可以看出,建立一個新的物件其實也算是物件生命週期的一環,所以 Repository 有時也會負責物件的建立。當然 如果建立的過程很複雜,可以採另一個 pattern: Factory 來輔助。

Repository 和 DAO 雖然同樣是處理資料,但是 Repository 著眼點和 DAO 並不一樣。DAO 只知道存取資料這種事,不會從物件的生命週期去思考。而物件的生命週期 和 business logic 是習習相關的,所以在設計上,Repository 是 domain 的一環,也會包含一些 business logic。比方說 AccountRepository 可能會 throw DuplicateAccountException 這種 business exception。如果是純 DAO 的話, 就不該寫這種東西了。

整理 DAO/Repository/Hibernate/JDBC 等之間的關係:

  • Pattern:
    • Repository -- 專職管理 Object 生命週期的物件。
    • DAO -- 專職處理資料的物件
  • Tools and Framework:
    • JDBC -- Java 處理 RDBMS 的工具
    • Hibernate -- Java 處理 Object 與 RDBMS mapping 的工具

Repository 和 DAO 都只是 pattern 的一種,可以應用在各種領域。 沒人規定 DAO 只能用在 JDBC,如果要處理 xml 資料,也可以套用 DAO 這個 pattern 來輔助。同理 Repository 也是一樣,跟 JDBC/Hibernate...這些工具一 點關係也沒有。再者 Design pattern 也跟 Java 也沒什麼關係,想在 C# 裡套用 Repository, DAO 也行。

把 Hibernate 和 Respository 綁在一起只是 POJOs in Action 作者的做法而已。 他覺得這兩個是完美的組合,所以他才寫書推廣他的理念。事實上也是如此,因為 Hibernate 提供很多方便管理 Object 生命週期的功能,所以寫起 Repository 變的很簡單。如果未來 Respository 真的很多人採用了,那麼 Hibernate 的功 勞可不小啊。

不過 Repository 這一詞在整個程式界裡不是很多人採用,有時候明明大家 寫的是 repository,卻也叫 DAO。所以大多數的時候只會看到 DAO 這個詞 。用 Repository 一詞的只有 Domain Driven Design 和 POJOs in Action 這兩本 書而已。

我個人是採用折衷的方式:我都管它們叫 DAO,而不是 Repository,一來 DAO 大家比較看的懂,二來 DAO 只要三個字母,比 Repository 短很多。 不過我的 DAO 也會兼差做些 Repository 的事就是了,但是比例很少,因為我不希望存取資料庫的程式碼混合 business logic,而且這樣 Unit Test 也不大好寫。

SQL:: JOIN


SQL Join語法

Join有兩種屬性:
INNER
OUTER

1.INNER
只顯示匹配的行.

2.OUTER
不論是否匹配,都顯示行.
LEFT, RIGHT, FULL 都帶有OUTER屬性

Join共有六種:
Inner Join
Natural Join
Left Outer Join
Right Outer Join
Full Outer Join
Cross Join

1.Inner Join
Inner Join其實等同於多個Where條件式的連結,

FROM a, b WHERE a.id = b.id AND b.val > 5
FROM a INNER JOIN b ON (a.id = b.id) WHERE b.val > 5
是一樣的

2.Natural Join
Natural Join只是自動的匹配兩個表之間相同的欄位,

FROM a, b WHERE a.id = b.id AND b.val > 5
FROM a NATURAL JOIN b WHERE b.val > 5
是一樣的.
可用在任何一種Inner 或 Outer Join.
Natural 與 USING 也是很相像的,只是Natural
只會讓兩個表的相同欄位出現一次.

3.Left Outer Join
4.Right Outer Join
其實這兩個幾乎是一樣的,只是方向性的不同.
以Left Outer Join來說,左邊顯示所有左表的值,而右邊顯示右表匹配的值.
如果沒有匹配的右表表,則放空值.
Right Outer Join則左右方向相反.

5.Full Outer Join
左右表都顯示,匹配的則顯示,沒有匹配的放空值.
好比把 Left Outer Join 和 Right Outer Join作聯集.

6.Cross Join
交叉連結,會得到兩個表的所有乘積組合.

From~ http://www.wretch.cc/blog/sky4s/2250385


[SQL]Join的觀念

前言

在位置上很常聽到人家討論SQL的時候,Join來Join去,害我每次都會回頭(因為聽起來實在很像在叫我的名字)。

小的自認為DB與SQL的功力,一向很薄弱。
而training新人時,第一個要解釋table與table之間關係,通常也是會講到join。

我雖然大概知道join是怎麼一回事,不過有時候解釋起來,看新人一臉疑惑的表情,也是讓我頗受傷的。

所以,上次看了呂老師書上的一張圖,
真的深深覺得一張圖加兩張table的範例資料,勝過千言萬語啊。

What is join?

Join,通常稱做交集,而交集是什麼呢?望文生義,看圖說故事,各位看官就會瞭解了。

這張圖,解釋了兩張表之間的關係。

兩張table,我們分別定義為Left table跟Right table。Left就是被交集的table (要稱做資料集合也可以),Right就是拿來交集的table。
就像A x B = C,我們稱A為被乘數,B為乘數,一樣的意思。

比較常看到的,Left table,就是Select * from [table1] ,這個from的table。
Right table,則是被join的那一張table,
例如

Select * from [table1]
Left join [table2] on [table1].fk=[table2].pk


在這例子,table2就是圖裡面的Right table。

而兩張table join的條件,也就是他們是靠什麼來做交集的,就是on後面的 [table1].fk=[table2].pk。
交集的條件不一定只有一個,Left table與Right table的交集後的結果,也有可能是空集合,也就是無符合的資料。

好,接著我們來給兩張表一些資料。

Table1:

PK FK
1 a1
2 a2
3 a3


Table2:

PK Description
a2 a2很棒
a3 a3很棒
a4 a4很棒

當我們現在join的條件是Table1.FK與Table2.PK。

  1. Inner Join,就代表Table1與Table2兩者,完全符合交集條件的資料集合。
    也就是上面圖裡面,兩個圈圈共同圈起來的那個部分,
    SQL的範例,通常inner join我們會直接寫
    • Select * from table1, table2
      Where table1.FK=table2.PK

      Inner Join代表的是兩個table共同的部分才要篩選出來,所以誰是Left,誰是Right其實沒有多大分別。

      於是,以我們的範例資料來說,這個例子會撈出
    • Table1_PK Table1_FK Table2_Description
      2 a2 a2很棒
      3 a3 a3很棒
  2. 除了Inner以外,當然就是Outer了。
    Outer又分兩種,一種是左邊的Outer,一種是右邊的Outer。
    什麼叫做左邊的Outer,在我們的圖裡面,就是左邊的圈圈全都要出來,而符合交集條件的右邊圈圈,資料也要帶出來。
    • Left join的SQL如下:
      Select * from table1
      Left outer join table2 on table1.FK = table2.PK

      在這例子,代表了table1就是我們的Left table,所以Left outer join後,table1所有資料都應該顯示出來,
      而符合table1.FK = table2.PK條件的資料,應該會帶出Table2的相關欄位資料。
    • Table1_PK Table1_FK Table2_Description
      1 null null
      2 a2 a2很棒
      3 a3 a3很棒

    • Right join的SQL如下:
      Select * from table1
      Right outer join table2 on table1.FK = table2.PK

      在這例子,table2代表我們的Right table,所以Table2所有資料應該顯示出來,並且符合交集條件的資料,應該有table1的欄位資料。
    • Table1_PK Table2_PK Table2_Description
      2 a2 a2很棒
      3 a3 a3很棒
      null a4 a4很棒

另外要提醒的,outer是可以省略的。而在Join裡面,Where條件扮演著什麼角色?
其實Where的條件,是用來限制Left table與Right table的Scope的。

所以where與join可以說毫無關係,因為是用來分別定義table的篩選條件,而非交集的條件。

希望不會在有朋友搞不清楚,到底什麼條件要放在join的on裡面,
什麼條件該放在where裡面。

用這張圖去思考一下,會幫您釐清許多的問題。

結論

  1. 上述的所有table,只是一種資料集合。也就是代表,它可以是另外一個子查詢後的結果。
  2. Left與Right的定義,則是被乘數與乘數的分別。
  3. Where只是篩選條件,拿來限制Left table與Right table的Scope。
  4. Inner Join沒有左右的差異,所以可以直接用兩張表的一個where 條件來表示,當然您要寫成inner join的表示法也會更符合這張圖的意義喔。
  5. Outer Join的Outer可以省略,但Left或Right則不能省略。

複雜或多層的Join,只是像寫程式剝洋蔥或穿衣服一樣,可以想像一行一行的join下來,每次都只有一個被乘數和乘數在做交集而已。
就像
a1 x a2 x a3 x a4,您會先計算a1 x a2後,再 x a3,之後的結果再 x a4一樣。




SQL:: GROUP BY, COUNT and HAVING

欲得知資源被使用次數大於 1 的報表。資源使用記錄儲存在資料表 rsu 中,其中 uno 欄位為資源代碼,資源每被使用一次 ,就會在 rsu 表中增加一筆使用記錄。故需使用 COUNT() 做計數動作,並指定搜尋條件為計數值大於 1 者。但在合計操作中 (It, '合計操作', means a query with aggregate method.) ,不能使用 WHERE 為條件表示,而應使用 HAVING 。

select rsu.uno, count(rsu.uno) as counts from rsu
where rsu.record_date = '2006-02-04'
group by rsu.uno having count(rsu.uno) > 1

最常見的 aggregate method 就是 SUM() 和 COUNT() 。由於 aggregate method 往往要搭配 GROUP BY 使用,因此對 GROUP BY 和 HAVING 的用法,產生了一個常見的誤解,即以為 HAVING 只能用在 GROUP BY 之後。然而, HAVING 其實是用於對 aggregate method 之結果作條件篩選,由於 aggregate method 可以不配合 GROUP BY 使用,所以 HAVING 也可以出現在沒有 GROUP BY 的查詢中。

java 面試題

今天主管拿了一份java試題給我做 ,真的難倒我了...
上了google打了關鍵字 ,發現網路上已經有人po出答案了...
總覺得網路上的答案和我想的有出路,這是我的答案..
不知道哪裡有正確答案....有人要給我正確答案嗎?

第一,談談final, finally, finalize的區別。

這三個沒什麼關係。
final是修飾的關鍵字,可修飾類別、方法 和變數。
final class該類別無法被繼承,final method 該方法不能被override,final variable
該變數一經設定後就無法修改。

finally 在例外處理中(try…catch….finally)最後一定會被執行的區塊。

finalize 當 garbage collector發現某物件已經不被任何物件所參考(reference)

會呼叫該物件的finalize(),finalize()內沒有什特別的動作一般會被

OVERRIDE拿來作為資源的釋放。


第二,Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其他類,是否可以implements(實現)interface(介面)?

可以,但不能同時extends和implements。(Anonymous inheritance)

Ex:
new ClassName ([參數列]) { 類別內容 }
new InterfaceName (){ 類別內容 }

第三,Static Nested Class 和 Inner Class的不同,說得越多越好。

Static Nested Class不能直接參考它的封裝類別(enclosing class)中的實
體變數或方法,僅能透過object instance的方式存取。
Inner Class可以直接存取它的封裝類別(enclosing class)中的變數或方法。
inner class中不能定義任何的static成員。


第四,&和&&的區別。

& 位元運算符號 && 邏輯運算符號

第五,HashMap和Hashtable的區別。

Hashtable 是thread safe class,HashMap不是。
HashMap 接受 null, 而 Hashtable 不接受。

第六,Collection 和 Collections的區別。
Collection是Interface,Collections是Class。

第七,什麼時候用assert。

測試驗證時。

第八,GC是什麼? 為什麼要有GC?

garbage collector,由JVM做記憶體管理,開發人員無須考慮這部分。

第九,String s = new String("xyz");創建了幾個String Object?

兩個… 一個是”xyz”另一個是new String(“xyz”)。

第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

Math.round(11.5) = 12 , Math.round(-11.5) = -11

第十一,short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?

S1 +1會回傳int,int不能指定給short;
S1 += 1 沒錯。

第十二,sleep() 和 wait() 有什麼區別?

Sleep()無法由其他thread喚起,wait()可以。

第十三,Java有沒有goto?

有,屬於沒有被實作的keyword。

第十四,陣列有沒有length()這個方法? String有沒有length()這個方法?

陣列僅有length的屬性,String有。

第十五,Overload和Override的區別。Overloaded的方法是否可以改變
返回值的類型?

Overload發生在同一類別裡,Override發生在繼承關係間。
Overload為靜態連結,Override為動態連結。
可改變返回值的型態,前提是參數也要變,參數相同傳回值不同是
不被允
許的。

第十六,Set裏的元素是不能重複的,那麼用什麼方法來區分重複與否呢?
是用==還是equals()? 它們有何區別?

用equals()。
==是比較refrence variables的內容,equals()是比較物件的內容。


第十七,給我一個你最常見到的runtime exception。
IndexOutOfBoundsException

第十八,error和exception有什麼區別?

Error 通常為不可補救的嚴重的錯誤,由 Java API或
Java virtual machine 自己丟出。

Exception 指較不嚴重的不正常狀況,他底下又定義了許多不同種類的子類別,
其中一類為 RuntimeException,表示 JVM 在執行期間發生的不正常情形。


第十九,List, Set, Map是否繼承自Collection介面?
List和Set是 ,Map不是

第二十,abstract class和interface有什麼區別?

當一個類別裡面包含有一個(含)以上的abstract method該稱類別為abstract class。
但在java中可故意宣告無abstract method的類別為abstract class。
在abstract class中可有屬性(資料成員),也可有已實作的method。

介面中全部都是abstract method並不能有constructor且僅能有
static final的屬性。


第二十一,abstract的method是否可同時是static,是否可同時是native,
是否可同時是synchronized?

不可,abstract method不可包含private, final, static, native,
synchronized
等關鍵字

第二十二,介面是否可繼承介面? 抽象類是否可實現(implements)介面?
抽象類別是否可繼承實體類別(concrete class)?

介面可繼承介面,抽象類別可implements介面,抽象類別可繼承實體類別
但前提是該實體類別要有明確的建構函數。。

第二十三,啟動一個執行緒是用run()還是start()?
start()會啟動一執行緒並呼叫其run()。

第二十四,構造器Constructor是否可被override?

No.

第二十五,是否可以繼承String類?

否,String是final Class。

第二十六,當一個執行緒進入一個物件的一個synchronized方法後,其他執行緒是否可進入此物件的其他方法?

可以。

第二十七,try {}裏有一個return語句,那麼緊跟在這個try後的finally {}裏的code會不會被執行,什麼時候被執行,在return前還是後?

會在return前執行。

第二十八,程式設計題: 用最有效率的方法算出2乘以8等於幾?

2 <<3

第二十九,兩個物件值相同(x.equals(y) == true),但卻可有不同的
hash code,這句話對不對?

java.lang.Object規範equals()傳回true時,必須擁有一樣的hashcode。
實作還是可以做到不一樣的hashcode。


第三十,當一個物件被當作參數傳遞到一個方法後,此方法可改變這個物件的屬性,
並可返回變化後的結果,那麼這裏到底是值傳遞還是引用傳遞?

Call by reference.

第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

Switch(exp),exp為整數運算式,故僅有int、 short、 char 或者 byte可以作用。

第三十二,程式設計題: 寫一個Singleton出來。

too easy...

619:
public class ClassicSingleton {

private static ClassicSingleton instance = null;
protected ClassicSingleton() {
// Exists only to defeat instantiation.
}
public static ClassicSingleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
}


From~http://chihhsiang-javaidea.blogspot.com/2007/07/java_29.html


=============

Concrete class:
當class 是 abstract class,所以無法實體化(instantiated),也就是說不能產生一個物件由於我們不能產生一個抽象類別的物件,所以對於非抽象類別,我們一般稱之為實體類別(concrete class)

Polymorphism:
Polymorphism又稱為多型,簡單來說,多型是指子類別繼承父類別時,同時改寫父類別的函式或變數,而我們可以宣告一個屬於父類別的變數,去存取子類別中改寫自父類別的函式或變數,這我們稱之為多型。
舉個生活一點的例子,若有一個父類別是動物,那麼有一個子類別鳥繼承自動物這個類別,當我們看到鳥的時侯,可以說牠是一隻鳥,也可以說牠是一隻動物。同樣的東西,卻有不同的表示型態。


Overloaded methods
are methods with the same name signature but either a different number of parameters or different types in the parameter list. For example 'spinning' a number may mean increase it, 'spinning' an image may mean rotate it by 90 degrees. By defining a method for handling each type of parameter you achieve the effect that you want.

Overridden methods are methods that are redefined within an inherited or subclass. They have the same signature and the subclass definition is used.

Polymorphism is the capability of an action or method to do different things based on the object that it is acting upon. This is the third basic principle of object oriented programming. Overloading and overriding are two types of polymorphism .

Java Garbage Collection (Java GC)

JVM使用的記憶體

Java Heap
1. Java 程式執行時,JVM 用來配置Java objects 的記憶體
2. GC 發生作用的記憶體
3. 預設值 (僅供參考)
*Xms大約都是4MB
*Xmx
1.AIX 為64MB
2.Windows 為實體記憶體的二分之一(16MB ~ 2GB -1)
3.Linux 為實體記憶體的二分之一(16MB ~ 512MB -1)

Native Heap

1. JVM 用來它內部運作的記憶體
2. JNI: Third party 的native module
3. 大小取決於產生的程式碼、產生的thread、GC 時用於保存javaobject 資訊
與產生或最佳化程式碼時的暫存空間
4. 預設值 (僅供參考) *128K(會隨著需求往上增長)

GC三部曲

1. Mark Phase
* 搜尋Java Heap 內全部的物件,找出已經沒有在使用中的物件
2. Sweep Phase
* 將無用的物件清除
3. Compaction Phase(optional)
*搬動物件,壓實Java Heap ,藉以移除物件之間的空白空間
*有些物件是無法搬動 Pinned (pointer 來自JNI, thread) , Dosed (pointer 來自stack)

GC的天時地利

* 當物件實體(Instance)沒有被參考時, 才允許被回收
* 參閱圖1範例判斷物件A~E,變成允許回收的順序 (A→B 為B被A所參考)
* 範例程式碼
    1: public void method1(){
2: Myclass a = new Myclass();
3: a = null; //步驟2產生的物件可以被gc

4: java.util.Date d = new java.util.Date();
5: d = new java.util.Date( long_date ); //步驟4產生的物件可以被gc
6: } //步驟5產生的物件可以被gc

*下面程式碼中A B C變成允許回收的順序?
     class OBJ{
private static A a = new A();
public B b = new B();

public void method1(){
C c = new C();
}
}


* 只能建議GC時機,但實際執行由JVM決定. 建議JVM執行GC方式如下
1. System.gc()
2. Runtime.getRuntime().gc()

* finalize()
1. finalize方法位於Java.Object
2. 當物件被JVM回收時會呼叫
3. 一般可用來手動釋放資源



From~http://chihhsiang-javaidea.blogspot.com/2007/10/java-garbage-collection.html

Java Web層框架比較—— JSF、Spring MVC、Stripes、Struts 2、Tapestry和Wicket

【譯者按】這是Matt Raible在今年(2007)6月24-27號召開的JA-SIG夏季會議上所作的主題演講,Matt從眾多方面對Java Web層框架做了一個全面、深入的比較。筆者認為這是一份及時的文檔,它對開發者如何判定一個Web層框架的好壞、如何選擇適合自己項目的框架有極大的指導作用。本文是對Matt Raible演講稿的整理歸納。
【作者介紹】Matt Raible,開源框架AppFuse的發起者、主要開發者;《Professional JSP 2.0》、《Spring Live》等書的作者;眾多會議的演講者,MySQL User Conference, ApacheCon, ApacheCon EU等;現任Raible Designs的CEO。

首先,Matt以自己的實踐經驗,指出了Java Web層框架——JSF、Spring MVC、Stripes、Struts 2、Tapestry和Wicket他們各自的優、缺點:

JSF
優點:
Java EE標準,這意味著有很大的市場需求和更多的工作機會
上手快速並且相對容易
有大量可用的組件庫
缺點:
大量的JSP標簽
對REST和安全支持不好
沒有一個統一的實現。既有SUN的實現,又有Apache的實現——MyFaces。

Spring MVC
優點:
對覆蓋綁定(overriding binding)、驗證(validation)等提供生命周期管理
與許多表示層技術/框架無縫集成:JSP/JSTL、Tiles、Velocity、FreeMarker、Excel、XSL、PDF等
便於測試——歸功於IoC
缺點:
大量的XML配置文件
太過靈活——沒有公共的父控制器
沒有內置的Ajax支持

Stripes
優點:
不需要書寫XML配置文件
良好的學習文檔
社區成員很熱心
缺點:
社區比較小
不如其他的項目活躍
ActionBean里面的URL是硬編碼的

Struts 2
優點:
架構簡單——易於擴展
標記庫很容易利用FreeMarker或者Velocity來定制
基於控制器或者基於頁面的導航
缺點:
文檔組織得很差
對新特征過分關註
通過Google搜索到的大多是Struts 1.x的文檔

Tapestry
優點:
一旦學會它,將極大地提高生產率
HTML模板——對頁面設計師非常有利
每出一個新版本,都會有大量的創新
缺點:
文檔過於概念性,不夠實用
學習曲線陡峭
發行周期長——每年都有較大的升級

Wicket
優點:
對Java開發者有利(不是Web開發者)
頁面和顯示綁定緊密
社區活躍——有來自創建者的支持
缺點:
HTML模板和Java代碼緊挨著
需要對OO有較好的理解
Wicket邏輯——什麽都用Java搞定

接著,Matt通過采訪這些框架的作者,與他們討論各種開源的Java Web框架,並且突出各個框架的長處、聽取框架作者對其他框架的看法,希望借此了解這些框架的未來發展方向。

下列是一些被采訪者:
JSF, Jacob Hookom
RIFE, Geert Bevin
Seam, Gavin King
Spring MVC, Rob Harrop
Spring Web Flow, Rob Harrop and Keith Donald
Stripes, Tim Fennell
Struts 1, Don Brown
Tapestry, Howard Lewis Ship
Trails, Chris Nelson
Struts 2, Patrick Lightbody
Wicket, Eelco Hillenius

Matt對采訪做了如下總結:
JSF:
如果你想讓web應用具有類似桌面程序的功能性,那麽JSF的標準規範和大量第三方組件庫的支持值得你 信賴。
Spring MVC:
綜合了許多不同的技術,這使得它可以被廣泛地應用到不同類型的項目中去;它可以被當作web應用開發的一個基礎平臺。
Stripes:
可以被應用到存在大量複雜數據交互的程序中;有強大的類型轉換、綁定和驗證功能;可以使管理大的複雜表單以及直接映射它們到域對象變得簡單……
Tapestry:
在中到大型項目中,表現突出(當然,你也可以只把它應用到單個頁面上),在這些項目中,你可以通過簡單地創建新的組件起到杠桿作用。
Struts 2:
通常更適合於那些希望可以真正開始做事並且願意花費大量時間來學習他們使用的開源工具的小項目組。Struts 2的目標不是那些更喜歡拖放式開發的“扶手椅程序員”。
Wicket:
非常適合於這樣的內/外部網應用:UI很複雜並且你希望可以充分利用你的開發者資源。

上面的總結,基本是突出了各個框架的長處。然而,哪些又是他們不好的地方呢?

Matt提出了評價一個框架好壞與否的標準:
Ajax支持 是不是內置了?是否便於使用?
書簽能力 用戶能否將某個頁面收藏起來並且可以方便地返回到該頁面?
驗證 使用是否簡單?是否支持客戶端(JavaScript)驗證?
可測試性 脫離容器測試控制器,是否足夠簡單?
提交和重定向 框架如何處理重複提交問題?
國際化 如何支持國際化?控制器利用國際化信息,是否容易?
頁面修飾 框架支持哪種類型的頁面修飾/組成機制?
社區和技術支持 提出問題,能否被快速地、恭敬地回答?
開發工具 是否有支持這個框架的好的工具,尤其是IDE?
市場需求 學習了這個框架,它能否幫你找到份工作?
崗位數量 在dice.com和indeed.com上,對這個框架技能的需求如何?

筆者認為這個評價標準,值得大家借鑒。

然後,Matt按照這些評價標準,對各個框架做了以下闡述:
Ajax支持
JSF:沒有內置的Ajax支持,需要使用ICEfaces和Ajax4JSF
Stripes:沒有對應的類庫,支持流輸出
Struts 2:內置Dojo,有用於GWT和JSON的插件
Spring MVC:沒有對應的類庫,需要使用DWR和Spring MVC擴展
Tapestry:Tapestry 4.1中,有內置的Dojo
Wicket:有Dojo和Script.aculo.us支持

書簽能力
JSF:可以任意提交——URL甚至不被考慮
Stripes:使用約定,但是你可以不加理會
Struts 2:有命名空間的概念,這使得收藏某個頁面並返回變得容易
Spring MVC:允許完全的URL控制
Tapestry:依然存在一些醜陋的URL
Wicket:允許裝配(mount)頁面/URL

驗證
JSF:默認的國際化信息醜陋,但是配置簡單
Stripes和Wicket:用Java類進行驗證——不支持客戶端驗證
Struts 2:使用OGNL完成強大的表達式驗證功能;只有在Action上指定了規則,才支持客戶端驗證。
Spring MVC:允許你使用公共驗證器——這是一種成熟的解決方案
Tapestry:有健壯的驗證功能——不需自定義就有漂亮的國際化信息

可測試性
Spring MVC和Struts 2:允許利用mocks(例如EasyMock、jMock和Spring Mocks)簡單地進行測試
Tapestry:測試困難,因為頁面類被抽象、具體類被簡化
JSF:頁面類可以方便地被測試,實際上很像Struts 2 中的actions
Wicket:有WicketTester——一個強大的解決方案
Stripes:有Servlet API Mocks和MockRoundtrip

提交和重定向
解決重複提交問題的最簡單方法是:在提交後重定向
Spring MVC:允許你將參數加到重定向URL上
Stripes、Tapestry和Wicket:有“flash式”的支持
Struts 2:需要一個自定義的解決方案
JSF:需要一個自定義的解決方案,國際化信息很難加入到頁面bean中

國際化
JSTL的標簽使國際化變得簡單;如何將國際化信息放到控制器類中,還沒有一個統一的標準。
Stripes、Spring MVC和JSF:每個地區使用一個資源綁定文件
Struts 2、Tapestry和Wicket:提倡把每個頁面/action用到的資源文件分開
JSF:需要在每個頁面上定義資源綁定信息
Tapestry:標簽比較可怕

頁面修飾
Tiles能夠用於Struts 2、Spring MVC和JSF中;需要對每個頁面進行配置。
SiteMesh能夠用於所有的這些框架中(不推薦在JSF、Tapestry或者Wicket中使用);在設置完成後, 只需要很少的維護。

開發工具
Spring MVC:Spring IDE,但是只做XML校驗,不是一個UI/web工具
Struts 2:Eclipse
Tapestry:Spindle,對編碼者非常有利
JSF:眾多IDE支持,並且做得越來越好
Stripes和Wicket:沒有任何官方工具
NetBeans目前支持Struts *、JSF(+Facelets)、Tapestry和Wicket,尚不支持Stripes和Spring MVC