|
在JScript的眾多運算符里,提供了三個邏輯運算符&&、||和!,噢?! 是高級語言都提供的。按我們對邏輯運算的正常認識,邏輯運算的結果因該是ture或者false。但是JScript的邏輯運算卻不完全是這么定義的,這里只有!運算符總是返回true|false,而||和&&運算比較的好玩。
JScript對于邏輯運算的true|false是這么定義的:
可是邏輯運算符||和&&雖然遵循上面的定義規則,但是它們返回的值卻很有意思。
對于&&運算,按照上面的規則,表達式 if ( 'abc' && '123' && new Date() ) 是執行true分支,可是這個表達式如果寫成:
結果value=Fri Jan 21 00:01:17 UTC+0800 2005,原它從左到右檢測,如果到了最后一個表達式也是為true的,就返回那個表達式。
對于||運算同理,對于下面的表達式:
結果value1='abc',value2='ok'。這是因為||運算會有"短路"特性,他也是從左向右檢測,只不過它是一但發現有為true的值,就立即返回該表達式。
這樣的特性可以幫組我們寫出精簡的代碼,可是同時也帶來代碼不便于閱讀維護的問題。
由于我手頭暫時沒有NS和moz什么的瀏覽器,不知道標準JavaScript是否也是這樣支持的?如果您方便的話,請告如我運行后的結果
有時你可能需要對變量進行類型檢查,或者判斷變量是否已定義。有兩種方法可以使用:typeof函數與constructor屬性。
typeof函數的用法可能不用我多說,大家都知道怎么用。而constructor屬性大家可能就陌生點。在《精通JavaScript》這本書中有提到construct的用法,但我用自己的幾個瀏覽器(IE7.0 / Firefox1.9 / Opera9.50)測試的結果卻和書上說的不一樣。但是仍然是有辦法通過constructor屬性來檢查變量類型的。
這里先補充一下,為什么明明有typeof函數可以很方便地用來檢測類型,還要用constructor呢?
因為typeof會把所有的數組類型以及用戶自定義類型判斷為object,從而無法知道更確切的信息。而constructor卻可以解決這個問題。
ok,明白了我們為什么要用constructor,現在讓我帶大家一步步認識一下typeof和constructor用法之間的差異吧~
首先我們運行一下下面這段代碼:
這3行代碼告訴你什么情況下可以用constructor。
你可以看到第2行返回了字符串'undefined',而第三行則發生了錯誤,原因是i變量還沒有類型定義,自然也沒有constructor的存在。
從這一點上看,typeof可以檢查到變量是否有定義,而construct只能檢查已定義變量的類型。
再運行一下下面這段代碼:
你會看到第2行返回了字符串'number’,第3行返回了一串類似函數定義的代碼字符串(這就是跟《精通JavaScript》一書中介紹的不一樣的地方)。
我們再用typeof檢查一下constructor到底是個什么樣類型的屬性,第4行返回結果'function',也就是說,實際上constructor是一個函數,更確切地說是一個構造函數。這時你就可以知道,為什么constructor可以檢查出各種類型了。
有經驗的程序員看到這里應該知道要怎么利用constructor來檢查變量類型了。方法有多種,這里提供一種比較容易理解的方法。
其實想法很簡單,就是把construcor轉化為字符串,通過尋找匹配字符串(function名)來確定是否指定類型。如下例子:
這僅僅是個簡單的例子。如果返回true則變量i不是user類型,返回false則變量是user類型。
當然,這樣檢測是不夠精確的,比如其實他是一個myuser類型的時候,同樣會被認為是user類。所以你需要書寫更精確的正則表達式去進行匹配。
可以這樣簡單改進你的正則表達式:
替換上面代碼段中的/user/。當然,如果你的構造函數原型是user(a),那么應該這樣書寫你的正則表達式:
到這里你應該知道怎樣使用constructor類型去檢查變量類型了吧?
ok,最后再提個醒,如果你要用基于constructor的方法去檢查一些基本類型,如
Object / Array / Function / String / Number / Boolean
在你的正則表達式中,一定要將這些單詞的首字母大寫!!而如果該類型是自定義類型,則根據你定義的時候標識符的寫法確定。
很多朋友在深入的接觸JAVA語言后就會發現這樣兩個詞:反射(Reflection)和內省(Introspector),經常搞不清楚這到底是怎么回事,在什么場合下應用以及如何使用?今天把這二者放在一起介紹,因為它們二者是相輔相成的。
反射
相對而言,反射比內省更容易理解一點。用一句比較白的話來概括,反射就是讓你可以通過名稱來得到對象(類,屬性,方法)的技術。例如我們可以通過類名來生成一個類的實例;知道了方法名,就可以調用這個方法;知道了屬性名就可以訪問這個屬性的值。
還是寫兩個例子讓大家更直觀的了解反射的使用方法:
上面的兩個例子是比較常用方法。看到上面的例子就有人要發問了:為什么要這么麻煩呢?本來一條語句就完成的事情干嗎要整這么復雜?沒錯,在上面的例子中確實沒有必要這么麻煩。不過你想像這樣一個應用程序,它支持動態的功能擴展,也就是說程序不重新啟動但是可以自動加載新的功能,這個功能使用一個具體類來表示。首先我們必須為這些功能定義一個接口類,然后我們要求所有擴展的功能類必須實現我指定的接口,這個規定了應用程序和可擴展功能之間的接口規則,但是怎么動態加載呢?我們必須讓應用程序知道要擴展的功能類的類名,比如是test.Func1,當我們把這個類名(字符串)告訴應用程序后,它就可以使用我們第一個例子的方法來加載并啟用新的功能。這就是類的反射,請問你有別的選擇嗎?
內省
內省是Java語言對Bean類屬性、事件的一種缺省處理方法。例如類A中有屬性name,那我們可以通過getName,setName來得到其值或者設置新的值。通過getName/setName來訪問name屬性,這就是默認的規則。Java中提供了一套API用來訪問某個屬性的getter/setter方法,通過這些API可以使你不需要了解這個規則(但你最好還是要搞清楚),這些API存放于包java.beans中。
一般的做法是通過類Introspector來獲取某個對象的BeanInfo信息,然后通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,然后我們就可以通過反射機制來調用這些方法。下面我們來看一個例子,這個例子把某個對象的所有屬性名稱和值都打印出來:
Web開發框架Struts中的FormBean就是通過內省機制來將表單中的數據映射到類的屬性上,因此要求FormBean的每個屬性要有getter/setter方法。但也并不總是這樣,什么意思呢?就是說對一個Bean類來講,我可以沒有屬性,但是只要有getter/setter方法中的其中一個,那么Java的內省機制就會認為存在一個屬性,比如類中有方法setMobile,那么就認為存在一個mobile的屬性,這樣可以方便我們把Bean類通過一個接口來定義而不用去關系具體實現,不用去關系Bean中數據的存儲。比如我們可以把所有的getter/setter方法放到接口里定義,但是真正數據的存取則是在具體類中去實現,這樣可提高系統的擴展性。
總結
將Java的反射以及內省應用到程序設計中去可以大大的提供程序的智能化和可擴展性。有很多項目都是采取這兩種技術來實現其核心功能,例如我們前面提到的Struts,還有用于處理XML文件的Digester項目,其實應該說幾乎所有的項目都或多或少的采用這兩種技術。在實際應用過程中二者要相互結合方能發揮真正的智能化以及高度可擴展性。
摘要: 原文出處:http://blog.chenlb.com/2008/11/join-or-countdownlatch-make-main-thread-wait-all-sub-thread.html 在編寫多線程的工作中,有個常見的問題:主線程(main) 啟動好幾個子線程(task)來完成并發任務,主線程要等待所有的子線程完成之后才繼續執行main的其它任務。 默認主線程退出時其它子線程不... 閱讀全文這是jQuery里常用的2個方法。
他們2者功能是完全不同的,而初學者往往會被誤導。
首先 我們看.find()方法:
現在有一個頁面,里面HTML代碼為:
如果我們使用find()方法:
將會輸出:
如果使用filter()方法:
將會輸出:
也許你已經看出它們的區別了。
find()會在div元素內 尋找 class為rain 的元素。
而filter()則是篩選div的class為rain的元素。
一個是對它的子集操作,一個是對自身集合元素篩選。
另外find()其實還可以用選擇器表示:
以前在Windows上ssh登錄一直都是用putty,雖然它簡單小巧,但畢竟缺少很多特性。今天試了一下SecureCRT,感覺用起來比Putty好多了,但SecureCRT默認的字體超難看,而且中文字體設置也比較麻煩一點,在這里記錄一下以后可能還用得到。
簡單的幾步下來就設置好了,如果還有亂碼的話就退出然后重新登陸一下。如果你想所有的連接都使用這個默認配置,可以在“全局選項”中設置“默認的會話選項”,這樣以后新建的連接會自動應用上面的設置了。
PS:
以前用putty的時候,字體就直接用我在Linux最愛的Monaco,但在SecureCRT中用Monaco字體的話,中文會顯示為亂碼,這是因為Monaco字體中不包含中文字符,而SecureCRT也不會自動的選擇系統默認的中文字體。
為了解決這個問題,我們只要去找一個包含中文的等寬字體來用,我從網上找了一個Consolas和雅黑的混合字體,雖然沒有Monaco好看,但效果也還不錯。這里有個地方需要注意一下,在選擇這個字體的字體選擇對話框中,字體的默認字符集是“西方”,需要改成CHINESE_GB2312。
如果你也想用這個字體的話,可以從這里下載。
這些操作對經常使用hibernate的同學已經很熟悉了,我也經常用但一些細節并不了解,
最近遇到問題才開始有看了一下。
在讀完robbin的這兩個精華貼的時候,感覺清晰了很多,確實好文章。
http://www.javaeye.com/topic/2712
http://www.javaeye.com/topic/1604?page=1
還有這個精華貼
http://www.javaeye.com/topic/7484
也很不錯。
里面總結的很好了,我結合以上三個帖子、自己的試驗(版本hibernate-3.0.5)和Hibernate文檔也總結了一點,加深理解。希望對剛開始學Hibernate的同學有所幫助。
一、saveorUpdate與unsaved-value
到底是sava還是update
Hibernate需要判斷被操作的對象究竟是一個已經持久化過的持久對象還是臨時對象。
1).主鍵Hibernate的id generator產生
<id name="id" type="java.lang.Long">
<column name="ID" precision="22" scale="0" />
<generator class="increment" />
</id>
Project project = new Project();
project.setId(XXX);
this.projectDao.saveOrUpdate(project);
1、默認unsaved-value="null"
主鍵是對象類型,hebernate判斷project的主鍵是否位null,來判斷project是否已被持久化
是的話,對project對象發送save(project),
若自己設置了主鍵則直接生成update的sql,發送update(project),即便數據庫里沒有那條記錄。
主鍵是基本類型如int/long/double/
自己設置unsaved-null="0"。
所以這樣的話save和update操作肯定不會報錯。
2、unsaved-value="none",
由于不論主鍵屬性為任何值,都不可能為none,因此Hibernate總是對project對象發送update(project)
3、unsaved-value="any"
由于不論主鍵屬性為任何值,都肯定為any,因此Hibernate總是對project對象發送save(project),hibernate生成主鍵。
Hibernate文檔中寫到
saveOrUpdate()完成了如下工作:
如果對象已經在這個session中持久化過了,什么都不用做
如果對象沒有標識值,調用save()來保存它
如果對象的標識值與unsaved-value中的條件匹配,調用save()來保存它
如果對象使用了版本(version或timestamp),那么除非設置unsaved-value="undefined",版本檢查會發生在標識符檢查之前.
如果這個session中有另外一個對象具有同樣的標識符,拋出一個異常
2).主鍵由自己來賦值
<id name="id" type="java.lang.Long">
<column name="ID" precision="22" scale="0" />
<generator class="assigned" />
</id>
Project project = new Project();
project.setId(XXX);
this.projectDao.saveOrUpdate(project);
1、默認unsaved-value="null"
這時有所不同,hibernate會根據主鍵產生一個select,來判斷此對象是否已被持久化
已被持久化則update,未被持久化則save。
2、unsaved-value="none",update對象,同上
3、unsaved-value="any" ,save對象,
如果自己自己設置的ID在數據庫中已存在,則報錯。
二、save與update操作
顯式的使用session.save()或者session.update()操作一個對象的時候,實際上是用不到unsaved-value的
在同一Session,save沒什么可說得
update對象時, 最直接的更改一個對象的方法就是load()它,保持Session打開,然后直接修改即可:
Session s =…
Project p = (Project) sess.load(Project.class, id) );
p.setName(“test”);
s.flush();
不用調用s.update(p);hibernate能察覺到它的變化,會自動更新。當然顯示調用的話也不會錯
Hibernate文檔中寫到
update()方法在下列情形下使用:
程序在前面的session中裝載了對象
對象被傳遞到UI(界面)層
對該對象進行了一些修改
對象被傳遞回業務層
應用程序在第二個session中調用update()保存修改
三、delete操作
刪除時直接自己構造一個project即可刪除
this.projectDao.delete(preojct);
以前刪除我是這樣寫的
public void deleteProject(String id) {
Project project = (Project) this.projectDao.get(Project.class, id);
if (project != null) {
this.projectDao.delete(project);
}
即這樣也是可以的
Project project = new Project();
project.setId(id);
this.projectDao.delete(project).
如果有級聯關系,需要把級聯的子類也構造出來add進去,同樣可以刪除。
好了,羅嗦的夠多了。