JAVA架構(gòu)師學(xué)習(xí)方向
posted @ 2018-10-26 14:12 JavaSuns 閱讀(182) | 評(píng)論 (0) | 編輯 收藏
SunsplHello,everyone,i am sun.
天道酬勤,笨鳥先飛.
隨筆 - 47, 文章 - 0, 評(píng)論 - 24, 引用 - 0
|
JAVA架構(gòu)師學(xué)習(xí)方向請(qǐng)點(diǎn)我查閱:JAVA架構(gòu)師
posted @ 2018-10-26 14:12 JavaSuns 閱讀(182) | 評(píng)論 (0) | 編輯 收藏 POI操作package cc.dynasoft.struts.action; posted @ 2009-06-13 19:52 JavaSuns 閱讀(612) | 評(píng)論 (0) | 編輯 收藏 linux創(chuàng)建文件夾命令
mkdir /home/u1 創(chuàng)建文件夾/home/u1
chown oracle /home/u1 表示改變目錄所有者為oracle賬戶; chgrp dba /home/u1 改變/home/u1目錄為dba所有; chmod 755 /home/u1 表示oracle賬戶對(duì)/home/u1目錄有755權(quán)限; rmdir /home/u1 表示刪除/home/u1目錄 hostname可以查看linux的計(jì)算機(jī)名; whoami可以查看當(dāng)前用戶; pwd顯示當(dāng)前路徑; df查看系統(tǒng)的硬件信息 ls -lrt l表示顯示詳細(xì)列表,-t表示按時(shí)間排序,-r反向排序 cat orcl_ora_3436.trc|grep bucket 以下查看相關(guān)文件內(nèi)容: more /etc/oratab cat /etc/passwd cat /etc/group posted @ 2008-07-28 09:01 JavaSuns 閱讀(38656) | 評(píng)論 (4) | 編輯 收藏 Linux中復(fù)制文件或目錄的命令(為了響應(yīng)新工作,要學(xué)習(xí)一下LINUX)copy命令 該命令的功能是將給出的文件或目錄拷貝到另一文件或目錄中,同MSDOS下的copy命令一樣,功能十分強(qiáng)大。 語法: cp [選項(xiàng)] 源文件或目錄 目標(biāo)文件或目錄 說明:該命令把指定的源文件復(fù)制到目標(biāo)文件或把多個(gè)源文件復(fù)制到目標(biāo)目錄中。 該命令的各選項(xiàng)含義如下: - a 該選項(xiàng)通常在拷貝目錄時(shí)使用。它保留鏈接、文件屬性,并遞歸地拷貝目錄,其作用等于dpR選項(xiàng)的組合。 - d 拷貝時(shí)保留鏈接。 - f 刪除已經(jīng)存在的目標(biāo)文件而不提示。 - i 和f選項(xiàng)相反,在覆蓋目標(biāo)文件之前將給出提示要求用戶確認(rèn)?;卮饄時(shí)目標(biāo)文件將被覆蓋,是交互式拷貝。 - p 此時(shí)cp除復(fù)制源文件的內(nèi)容外,還將把其修改時(shí)間和訪問權(quán)限也復(fù)制到新文件中。 - r 若給出的源文件是一目錄文件,此時(shí)cp將遞歸復(fù)制該目錄下所有的子目錄和文件。此時(shí)目標(biāo)文件必須為一個(gè)目錄名。 - l 不作拷貝,只是鏈接文件。 需要說明的是,為防止用戶在不經(jīng)意的情況下用cp命令破壞另一個(gè)文件,如用戶指定的目標(biāo)文件名已存在,用cp命令拷貝文件后,這個(gè)文件就會(huì)被新源文件覆蓋,因此,建議用戶在使用cp命令拷貝文件時(shí),最好使用i選項(xiàng)。 posted @ 2008-07-28 08:59 JavaSuns 閱讀(2325) | 評(píng)論 (0) | 編輯 收藏 解析oracle的rownum(學(xué)習(xí))
對(duì)于rownum來說它是oracle系統(tǒng)順序分配為從查詢返回的行的編號(hào),返回的第一行分配的是1,第二行是2,依此類推,這個(gè)偽字段可以用于限制查詢返回的總行數(shù),而且rownum不能以任何表的名稱作為前綴。
舉例說明: 例如表:student(學(xué)生)表,表結(jié)構(gòu)為: ID char(6) --學(xué)號(hào) name VARCHAR2(10) --姓名 create table student (ID char(6), name VARCHAR2(100)); insert into sale values('200001',‘張一’); insert into sale values('200002',‘王二’); insert into sale values('200003',‘李三’); insert into sale values('200004',‘趙四’); commit; (1) rownum 對(duì)于等于某值的查詢條件 如 果希望找到學(xué)生表中第一條學(xué)生的信息,可以使用rownum=1作為條件。但是想找到學(xué)生表中第二條學(xué)生的信息,使用rownum=2結(jié)果查不到數(shù)據(jù)。因 為rownum都是從1開始,但是1以上的自然數(shù)在rownum做等于判斷是時(shí)認(rèn)為都是false條件,所以無法查到rownum = n(n>1的自然數(shù))。 SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回記錄條數(shù)的地方,保證不出錯(cuò),如:隱式游標(biāo)) SQL> select rownum,id,name from student where rownum=1; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 1 200001 張一 SQL> select rownum,id,name from student where rownum =2; ROWNUM ID NAME ---------- ------ --------------------------------------------------- (2)rownum對(duì)于大于某值的查詢條件 如果想找到從第二行記錄以后的記錄,當(dāng)使用rownum>2是查不出記錄的,原因是由于rownum是一個(gè)總是從1開始的偽列,Oracle 認(rèn)為rownum> n(n>1的自然數(shù))這種條件依舊不成立,所以查不到記錄 SQL> select rownum,id,name from student where rownum >2; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 那如何才能找到第二行以后的記錄呀。可以使用以下的子查詢方法來解決。注意子查詢中的rownum必須要有別名,否則還是不會(huì)查出記錄來,這是因?yàn)閞ownum不是某個(gè)表的列,如果不起別名的話,無法知道rownum是子查詢的列還是主查詢的列。 SQL>select * from(select rownum no ,id,name from student) where no>2; NO ID NAME ---------- ------ --------------------------------------------------- 3 200003 李三 4 200004 趙四 SQL> select * from(select rownum,id,name from student)where rownum>2; ROWNUM ID NAME ---------- ------ --------------------------------------------------- (3)rownum對(duì)于小于某值的查詢條件 如果想找到第三條記錄以前的記錄,當(dāng)使用rownum<3是能得到兩條記錄的。顯然rownum對(duì)于rownum<n((n>1的自然數(shù))的條件認(rèn)為是成立的,所以可以找到記錄。 SQL> select rownum,id,name from student where rownum <3; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 1 200001 張一 2 200002 王二 綜 上幾種情況,可能有時(shí)候需要查詢r(jià)ownum在某區(qū)間的數(shù)據(jù),那怎么辦呀從上可以看出rownum對(duì)小于某值的查詢條件是人為true的,rownum對(duì) 于大于某值的查詢條件直接認(rèn)為是false的,但是可以間接的讓它轉(zhuǎn)為認(rèn)為是true的。那就必須使用子查詢。例如要查詢r(jià)ownum在第二行到第三行之 間的數(shù)據(jù),包括第二行和第三行數(shù)據(jù),那么我們只能寫以下語句,先讓它返回小于等于三的記錄行,然后在主查詢中判斷新的rownum的別名列大于等于二的記 錄行。但是這樣的操作會(huì)在大數(shù)據(jù)集中影響速度。 SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2; NO ID NAME ---------- ------ --------------------------------------------------- 2 200002 王二 3 200003 李三 (4)rownum和排序 Oracle中的rownum的是在取數(shù)據(jù)的時(shí)候產(chǎn)生的序號(hào),所以想對(duì)指定排序的數(shù)據(jù)去指定的rowmun行數(shù)據(jù)就必須注意了。 SQL> select rownum ,id,name from student order by name; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 3 200003 李三 2 200002 王二 1 200001 張一 4 200004 趙四 可以看出,rownum并不是按照name列來生成的序號(hào)。系統(tǒng)是按照記錄插入時(shí)的順序給記錄排的號(hào),rowid也是順序分配的。為了解決這個(gè)問題,必須使用子查詢 SQL> select rownum ,id,name from (select * from student order by name); ROWNUM ID NAME ---------- ------ --------------------------------------------------- 1 200003 李三 2 200002 王二 3 200001 張一 4 200004 趙四 這樣就成了按name排序,并且用rownum標(biāo)出正確序號(hào)(有小到大) posted @ 2008-06-26 10:23 JavaSuns 閱讀(434) | 評(píng)論 (0) | 編輯 收藏 Java里的list,set,map操作方法(練習(xí))
//ArrayList
{ ArrayList arraylist=new ArrayList(); arraylist.add(0,"end");//指定索引加入值 //需注意的是,如果現(xiàn)有2個(gè)值,我加入索引為5的那么就會(huì)出現(xiàn)異常 for(int i=0;i<2;i++){ arraylist.add(i,String.valueOf(i)); } System.out.println("ArrayList:"); for(int i=0;i<arraylist.size();i++){ System.out.print(arraylist.get(i)+";"); } arraylist.add("0");//直接加入值到ArrayList的最后 arraylist.add("0"); System.out.print("\nArrayList\'s lastIndexOf(\"0\") is "+arraylist.lastIndexOf("0")); } //Arrays { String []array=new String[]{"a","b","c"}; List list=Arrays.asList(array); System.out.println("\nArrays:"); for(int i=0;i<list.size();i++){ System.out.print(list.get(i)+";"); } System.out.print("\nArrays\'s length is "+array.length);//打印數(shù)組的長(zhǎng)度 } //Collections { String []array=new String[]{"a","b","c"}; List list=Arrays.asList(array); Collections.fill(list,"Fill");//用Fill填充全部元素 System.out.println("\nCollections:"); for(int i=0;i<list.size();i++){ System.out.print(list.get(i)+";"); } array=new String[]{"1","2","3"}; List list2=Arrays.asList(array); Collections.copy(list,list2);//拷貝list2的數(shù)據(jù)進(jìn)list System.out.println("\n"+list); Collections.swap(list,2,1);//調(diào)換索引為1和2的元素的位置 System.out.println(list); } //EventObject { String s="hello"; String s2=s; EventObject eventobject=new EventObject(s);//一個(gè)準(zhǔn)容器類型,確切的歸類它不是容器 System.out.println("EventObject:"); System.out.println(eventobject.getSource()); System.out.println(eventobject.equals(s2)); } //HashMap { HashMap hashmap=new HashMap();//一個(gè)速度最快的容器 hashmap.put("0","c"); hashmap.put("1","a"); hashmap.put("2","b"); hashmap.put("3","a"); System.out.println("HashMap:"); System.out.println(hashmap);//該容器有其內(nèi)部的排序方式 Set set=hashmap.keySet();//獲取全部鍵 Iterator iterator=set.iterator(); while(iterator.hasNext()){ System.out.print(hashmap.get(iterator.next())+";"); } } //HashSet { HashSet hashset=new HashSet();//一個(gè)絕對(duì)不能重復(fù)的類型 hashset.add("c"); hashset.add("b"); hashset.add("a"); hashset.add("a"); hashset.add("b"); System.out.println("\nHashSet:"); System.out.println(hashset); Iterator iterator=hashset.iterator();//取出元素 while(iterator.hasNext()){ System.out.print(iterator.next()+";"); } } //Hashtable { Hashtable hashtable=new Hashtable();//一個(gè)完全可以由其他容器替換的老容器類型 hashtable.put("0","c"); hashtable.put("1","a"); hashtable.put("3","c"); hashtable.put("2","b"); System.out.println("\nHashtable:"); Enumeration enumeration=hashtable.elements();//獲取元素,Enumeration已經(jīng)不是主流,Iterator是它的下一代替代品 while(enumeration.hasMoreElements()){ System.out.print(enumeration.nextElement()+";"); } } //IdentityHashMap { IdentityHashMap identityhashmap=new IdentityHashMap(); identityhashmap.put("0","c"); identityhashmap.put("1","a"); identityhashmap.put("3","b"); identityhashmap.put("2","a"); System.out.println("\nIdentityHashMap:"); System.out.println(identityhashmap); System.out.println(identityhashmap.containsKey("3"));//是否包含這個(gè)鍵 System.out.println(identityhashmap.containsValue("a"));//是否包含值 Set set=identityhashmap.entrySet();//傳為Set類型 System.out.println(set); set=identityhashmap.keySet();//全部鍵 System.out.println(set); } //LinkedHashMap { LinkedHashMap linkedhashmap=new LinkedHashMap(); linkedhashmap.put("0","b"); linkedhashmap.put("2","a"); linkedhashmap.put("1","c"); linkedhashmap.put("3","b"); System.out.println("LinkedHashMap:"); System.out.println(linkedhashmap); System.out.println(linkedhashmap.containsKey("2"));//是否包含這個(gè)鍵 System.out.println(linkedhashmap.containsValue("c"));//是否包含值 Set set=linkedhashmap.keySet(); Iterator iterator=set.iterator(); while(iterator.hasNext()){ System.out.print(linkedhashmap.get(iterator.next())+";"); } } //LinkedHashSet { LinkedHashSet linkedhashset=new LinkedHashSet();//它包含了幾種Set的屬性但卻沒有自己的特色 linkedhashset.add("c"); linkedhashset.add("a"); linkedhashset.add("a"); linkedhashset.add("b"); System.out.println("\nLinkedHashSet:"); System.out.println(linkedhashset); System.out.println(linkedhashset.contains("a"));//是否包含對(duì)象 Iterator iterator=linkedhashset.iterator(); while(iterator.hasNext()){ System.out.print(iterator.next()+";"); } } //LinkedList { LinkedList linkedlist=new LinkedList();//自由使用是它的特色 linkedlist.add("a"); linkedlist.add(1,"c"); linkedlist.addLast("b"); linkedlist.addFirst("d"); System.out.println("\nLinkedList:"); System.out.println(linkedlist); //linkedlist.clear();//該方法清空容器 //linkedlist.remove(0);//刪除索引為0的元素 //linkedlist.remove("d");//刪除值為d的元素 //linkedlist.removeFirst();//刪除第一個(gè)元素 //linkedlist.removeLast();//刪除最后一個(gè)元素 for(int i=0;i<linkedlist.size();i++){ System.out.print(linkedlist.get(i)+";"); } } //Stack { Stack stack=new Stack();//堆棧 stack.add("b"); stack.add(0,"c"); stack.push("d"); stack.add("e"); stack.push("a"); Enumeration enumeration=stack.elements(); System.out.println("\nStack:"); while(enumeration.hasMoreElements()){ System.out.print(enumeration.nextElement()+";"); } //后進(jìn)先出 System.out.println("\n"+stack.peek()); System.out.println(stack.pop()); System.out.println(stack.contains("d")+";"+stack.contains("a"));//是否包含該元素,有趣的事情發(fā)生了 System.out.println(stack.search("c"));//非常有用的屬性,檢索,但是由后向前的排列 } //TreeMap { TreeMap treemap=new TreeMap(); treemap.put("0","d"); treemap.put("2","a"); treemap.put("1","b"); treemap.put("3","c"); System.out.println("\nTreeMap:");//可以對(duì)鍵排序 System.out.println(treemap); System.out.println(treemap.firstKey());//返回第一個(gè)鍵 Set set=treemap.keySet(); Iterator iterator=set.iterator(); while(iterator.hasNext()){ System.out.print(treemap.get(iterator.next())+";"); } } //TreeSet { TreeSet treeset=new TreeSet();//自動(dòng)排序內(nèi)容 treeset.add("b"); treeset.add("a"); treeset.add("c"); treeset.add("d"); System.out.println("\nTreeSet:"); System.out.println(treeset); System.out.println(treeset.first());//返回第一個(gè)元素 Iterator iterator=treeset.iterator(); while(iterator.hasNext()){ System.out.print(iterator.next()+";"); } } //Vector { Vector vector=new Vector(); vector.add(0,"b"); vector.add("a"); vector.addElement("d"); vector.add("c"); System.out.println("\nVector:"); System.out.println(vector); vector.set(2,"h");//替換掉指定索引的元素 System.out.println(vector); Object []str=vector.toArray(); for(int i=0;i<str.length;i++){ System.out.print(str[i]+";"); } vector.setSize(2);//重新設(shè)置大小為2 System.out.println("\n"+vector); } //WeakHashMap { WeakHashMap weakhashmap=new WeakHashMap(); weakhashmap.put("1","b"); weakhashmap.put("2","c"); weakhashmap.put("0","d"); weakhashmap.put("3","a"); System.out.println("\nWeakHashMap:"); System.out.println(weakhashmap); System.out.println(weakhashmap.containsKey("3"));//是否包含鍵 System.out.println(weakhashmap.containsValue("d"));//是否包含值 Set set=weakhashmap.entrySet(); Iterator iterator=set.iterator(); while(iterator.hasNext()){ System.out.print(iterator.next()+";"); } //weakhashmap.remove("2");//刪除該鍵對(duì)應(yīng)的值 //weakhashmap.get("1");//獲取指定鍵的值 } } posted @ 2008-06-25 17:33 JavaSuns 閱讀(3885) | 評(píng)論 (0) | 編輯 收藏 map,set,list,等JAVA中集合解析(了解)
在JAVA的util包中有兩個(gè)所有集合的父接口Collection和Map,它們的父子關(guān)系:
java.util +Queue 接口 +Set 接口 +Map 接口 以下對(duì)眾多接口和類的簡(jiǎn)單說明:首先不能不先說一下數(shù)組(Array) Java所有“存儲(chǔ)及隨機(jī)訪問一連串對(duì)象”的做法,array是最有效率的一種。 1、 2、Java中有一個(gè)Arrays類,專門用來操作array。
若撰寫程序時(shí)不知道究竟需要多少對(duì)象,需要在空間不足時(shí)自動(dòng)擴(kuò)增容量,則需要使用容器類庫(kù),array不適用。 1、Collection 和 Map 的區(qū)別 容器內(nèi)每個(gè)為之所存儲(chǔ)的元素個(gè)數(shù)不同。 2、Java2容器類類庫(kù)的用途是“保存對(duì)象”,它分為兩類,各自旗下的子類關(guān)系 Collection Map----一組成對(duì)的“鍵值對(duì)”對(duì)象,即其元素是成對(duì)的對(duì)象,最典型的應(yīng)用就是數(shù)據(jù)字典,并且還有其它廣泛的應(yīng)用。另外,Map可以返回其所有鍵組成的Set和其所有值組成的Collection,或其鍵值對(duì)組成的Set,并且還可以像數(shù)組一樣擴(kuò)展多維Map,只要讓Map中鍵值對(duì)的每個(gè)“值”是一個(gè)Map即可。 3、其他特征 * List,Set,Map將持有對(duì)象一律視為Object型別。
Collections是針對(duì)集合類的一個(gè)幫助類。提供了一系列靜態(tài)方法實(shí)現(xiàn)對(duì)各種集合的搜索、排序、線程完全化等操作。 四、如何選擇? 1、容器類和Array的區(qū)別、擇取 2、 結(jié)論:最常用的是ArrayList,HashSet,HashMap,Array。而且,我們也會(huì)發(fā)現(xiàn)一個(gè)規(guī)律,用TreeXXX都是排序的。
1、Collection沒有g(shù)et()方法來取得某個(gè)元素。只能通過iterator()遍歷元素。 5、Map用 put(k,v) / get(k),還可以使用containsKey()/containsValue()來檢查其中是否含有某個(gè)key/value。 6、Map中元素,可以將key序列、value序列單獨(dú)抽取出來。 為什么一個(gè)生成Set,一個(gè)生成Collection?那是因?yàn)椋琸ey總是獨(dú)一無二的,value允許重復(fù)。 posted @ 2008-06-25 17:32 JavaSuns 閱讀(11793) | 評(píng)論 (1) | 編輯 收藏 項(xiàng)目成功的12個(gè)關(guān)鍵原則(學(xué)習(xí))1、項(xiàng)目經(jīng)理必須關(guān)注項(xiàng)目成功的三個(gè)標(biāo)準(zhǔn) 簡(jiǎn)單地說,一是準(zhǔn)時(shí);二是預(yù)算控制在既定的范圍內(nèi);三是質(zhì)量得到經(jīng)理和用戶們的贊許。項(xiàng)目經(jīng)理必須保證項(xiàng)目小組的每一位成員都能對(duì)照上面三個(gè)標(biāo)準(zhǔn)來進(jìn)行工作。 2、任何事都應(yīng)當(dāng)先規(guī)劃再執(zhí)行 就項(xiàng)目管理而言,很多專家和實(shí)踐人員都同意這樣一個(gè)觀點(diǎn):需要項(xiàng)目經(jīng)理投入的最重要的一件事就是規(guī)劃。只有詳細(xì)而系統(tǒng)的由項(xiàng)目小組成員參與的規(guī)劃才是項(xiàng)目成功的唯一基礎(chǔ)。當(dāng)現(xiàn)實(shí)的世界出現(xiàn)了一種不適于計(jì)劃生存的環(huán)境時(shí),項(xiàng)目經(jīng)理應(yīng)制定一個(gè)新的計(jì)劃來反映環(huán)境的變化。規(guī)劃、規(guī)劃、再規(guī)劃就是項(xiàng)目經(jīng)理的一種生活方式。 3、項(xiàng)目經(jīng)理必須以自己的實(shí)際行動(dòng)向項(xiàng)目小組成員傳遞一種緊迫感 由于項(xiàng)目在時(shí)間、資源和經(jīng)費(fèi)上都是有限的,項(xiàng)目最終必須完成。但項(xiàng)目小組成員大多有自己的愛好,項(xiàng)目經(jīng)理應(yīng)讓項(xiàng)目小組成員始終關(guān)注項(xiàng)目的目標(biāo)和截止期限。例如,可以定期檢查,可以召開例會(huì),可以制作一些提醒的標(biāo)志置于項(xiàng)目的場(chǎng)所。 4、成功的項(xiàng)目應(yīng)使用一種可以度量且被證實(shí)的項(xiàng)目生命周期 標(biāo)準(zhǔn)的信息系統(tǒng)開發(fā)模型可以保證專業(yè)標(biāo)準(zhǔn)和成功的經(jīng)驗(yàn)?zāi)軌蛉谌腠?xiàng)目計(jì)劃。這類模型不僅可以保證質(zhì)量,還可以使重復(fù)勞動(dòng)降到最低程度。因此,當(dāng)遇到時(shí)間和預(yù)算壓力需要削減項(xiàng)目時(shí),項(xiàng)目經(jīng)理應(yīng)確定一種最佳的項(xiàng)目生命周期。 5、所有項(xiàng)目目標(biāo)和項(xiàng)目活動(dòng)必須生動(dòng)形象地得以交流和溝通 項(xiàng)目經(jīng)理和項(xiàng)目小組在項(xiàng)目開始時(shí)就應(yīng)當(dāng)形象化地描述項(xiàng)目的最終目標(biāo),以確保與項(xiàng)目有關(guān)的每一個(gè)人都能記住。項(xiàng)目成本的各個(gè)細(xì)節(jié)都應(yīng)當(dāng)清楚、明確、毫不含糊,并確保每個(gè)人對(duì)此都達(dá)成了一致的意見。 6、采用漸進(jìn)的方式逐步實(shí)現(xiàn)目標(biāo) 如果試圖同時(shí)完成所有的項(xiàng)目目標(biāo),只會(huì)造成重復(fù)勞動(dòng),既浪費(fèi)時(shí)間又浪費(fèi)錢。俗話說,一口吃不成個(gè)胖子。項(xiàng)目目標(biāo)只能一點(diǎn)一點(diǎn)地去實(shí)現(xiàn),并且每實(shí)現(xiàn)一個(gè)目標(biāo)就進(jìn)行一次評(píng)估,確保整個(gè)項(xiàng)目能得以控制。 7、項(xiàng)目應(yīng)得到明確的許可,并由投資方簽字實(shí)施 在實(shí)現(xiàn)項(xiàng)目目標(biāo)的過程中獲得明確的許可是非常重要的。應(yīng)將投資方的簽字批準(zhǔn)視為項(xiàng)目的一個(gè)出發(fā)點(diǎn)。道理很簡(jiǎn)單:任何有權(quán)拒絕或有權(quán)修改項(xiàng)目目標(biāo)的人都應(yīng)當(dāng)在項(xiàng)目啟動(dòng)時(shí)審查和批準(zhǔn)這些項(xiàng)目目標(biāo)。 8、要想獲得項(xiàng)目成功必須對(duì)項(xiàng)目目標(biāo)進(jìn)行透徹的分析 研究表明,如果按照眾所周知記錄在案的業(yè)務(wù)需求來設(shè)計(jì)項(xiàng)目的目標(biāo),則該項(xiàng)目多半會(huì)成功。所以,項(xiàng)目經(jīng)理應(yīng)當(dāng)堅(jiān)持這樣一個(gè)原則,即在組織機(jī)構(gòu)啟動(dòng)項(xiàng)目之前,就應(yīng)當(dāng)為該項(xiàng)目在業(yè)務(wù)需求中找到充分的依據(jù)。 9、項(xiàng)目經(jīng)理應(yīng)當(dāng)責(zé)權(quán)對(duì)等 項(xiàng)目經(jīng)理應(yīng)當(dāng)對(duì)項(xiàng)目的結(jié)果負(fù)責(zé),這一點(diǎn)并不過分。但與此相對(duì)應(yīng),項(xiàng)目經(jīng)理也應(yīng)被授予足夠的權(quán)利以承擔(dān)相應(yīng)的責(zé)任。在某些時(shí)候,權(quán)利顯得特別重要,如獲取或協(xié)調(diào)資源,要求得到有關(guān)的中小企業(yè)的配合,做相應(yīng)的對(duì)項(xiàng)目成功有價(jià)值的決策等等。 10、項(xiàng)目投資方和用戶應(yīng)當(dāng)主動(dòng)介入,不能被動(dòng)地坐享其成 多數(shù)項(xiàng)目投資方和用戶都能正確地要求和行使批準(zhǔn)(全部或部分)項(xiàng)目目標(biāo)的權(quán)力。但伴隨這個(gè)權(quán)力的是相應(yīng)的責(zé)任——主動(dòng)地介入項(xiàng)目的各個(gè)階段。例如,在項(xiàng)目早期要幫助確定項(xiàng)目目標(biāo);在項(xiàng)目進(jìn)行中,要對(duì)完成的階段性目標(biāo)進(jìn)行評(píng)估,以確保項(xiàng)目能順利進(jìn)行。項(xiàng)目投資方應(yīng)幫助項(xiàng)目經(jīng)理去訪問有關(guān)的中小企業(yè)和目標(biāo)顧客的成員,并幫助項(xiàng)目經(jīng)理獲得必要的文件資料。 11、項(xiàng)目的實(shí)施應(yīng)當(dāng)采用市場(chǎng)運(yùn)作機(jī)制 在多數(shù)情況下,項(xiàng)目經(jīng)理應(yīng)將自己看成是賣主,以督促自己完成投資方和用戶交付的任務(wù)。項(xiàng)目計(jì)劃一旦批準(zhǔn)項(xiàng)目經(jīng)理應(yīng)當(dāng)定期提醒項(xiàng)目小組成員該項(xiàng)目必須滿足的業(yè)務(wù)需求是什么,以及該怎樣工作才能滿足這些業(yè)務(wù)需求。 12、項(xiàng)目經(jīng)理應(yīng)當(dāng)獲得項(xiàng)目小組成員的最佳人選 最佳人選是指受過相應(yīng)的技能培訓(xùn),有經(jīng)驗(yàn),素質(zhì)高。對(duì)于項(xiàng)目來說,獲得最佳人選往往能彌補(bǔ)時(shí)間、經(jīng)費(fèi)或其它方面的不足。項(xiàng)目經(jīng)理應(yīng)當(dāng)為這些最佳的項(xiàng)目成員創(chuàng)造良好的工作環(huán)境,如幫助他們免受外部干擾,幫助他們獲得必要的工具和條件以發(fā)揮他們的才能。 posted @ 2008-06-15 15:43 JavaSuns 閱讀(351) | 評(píng)論 (0) | 編輯 收藏 什么是“成功項(xiàng)目”:談?wù)勡浖膬r(jià)值(看)在開始正文之前,我想先講兩個(gè)故事——關(guān)于軟件項(xiàng)目的故事。
有兩個(gè)軟件項(xiàng)目(姑且稱之為“項(xiàng)目 A”和“項(xiàng)目 B”),它們?cè)陂_始時(shí)的預(yù)算都是 50 個(gè)人月,時(shí)間是 5 個(gè)月。 項(xiàng)目 A 在 5 個(gè)月后完工,耗費(fèi)成本 50 人月 故事二 有兩個(gè)軟件項(xiàng)目(仍然姑且稱之為“項(xiàng)目 A”和“項(xiàng)目 B”),它們?cè)陂_始時(shí)的計(jì)劃都是交付 200 項(xiàng)功能。 項(xiàng)目 A 在項(xiàng)目結(jié)束時(shí)一次性交付了最初計(jì)劃的 200 項(xiàng)功能,但客戶發(fā)現(xiàn)其中大約 30 項(xiàng)功能沒有太大用處,而另外 30 項(xiàng)有用的功能要等到下一個(gè)項(xiàng)目才能實(shí)現(xiàn)。 這個(gè)問題并不容易回答——實(shí)際上它沒有標(biāo)準(zhǔn)答案。站在很多軟件企業(yè)的立場(chǎng)上,項(xiàng)目 A 是一個(gè)理想的成功項(xiàng)目:按時(shí)間、按成本完成預(yù)先約定的任務(wù)。請(qǐng)注意,我用了“理想的”這個(gè)詞,稍后我還會(huì)解釋這個(gè)有趣的詞,因?yàn)閷?shí)際上的軟件項(xiàng)目往往沒有那么理想。 而如果換一個(gè)角度,站在客戶的立場(chǎng)上呢?也許付錢購(gòu)買軟件的客戶會(huì)有一些不同的想法。項(xiàng)目 B 從開始之后一個(gè)月便交付了第一個(gè)可工作的版本,從那時(shí)起客戶就開始使用這個(gè)軟件的部分功能,并且不斷地把自己使用的感受反饋給開發(fā)團(tuán)隊(duì)。在真實(shí)的業(yè)務(wù)運(yùn)營(yíng)過程中,客戶甚至發(fā)現(xiàn)了一種新的盈利模式,并進(jìn)行了一次大規(guī)模的業(yè)務(wù)調(diào)整,這次調(diào)整的結(jié)果也直觀地體現(xiàn)在軟件項(xiàng)目中。雖然項(xiàng)目B的整體交付速率低于項(xiàng)目 A,但它提供的所有功能都是客戶真正需要的,它們?yōu)榭蛻籼峁?shí)實(shí)在在的價(jià)值——更不用說,客戶提前好幾個(gè)月就開始使用這個(gè)軟件。 實(shí)際上,這是一篇關(guān)于軟件價(jià)值的文章。和“成功項(xiàng)目”一樣,對(duì)于“軟件的價(jià)值”,不同的人也會(huì)有不同的定義。不過作為付錢購(gòu)買軟件的客戶,他對(duì)于軟件價(jià)值的定義是一目了然的:他能夠從使用軟件中創(chuàng)造多少價(jià)值,軟件能夠?yàn)樗臉I(yè)務(wù)提供多少價(jià)值,這就是軟件的價(jià)值。或者說得更簡(jiǎn)明一點(diǎn): 軟件價(jià)值源自使用 一個(gè)真實(shí)的案例 在 ThoughtWorks 的一個(gè)項(xiàng)目中,開發(fā)者們?cè)陧?xiàng)目開始之后一個(gè)月內(nèi)就發(fā)布了第一個(gè)版本——只有一些簡(jiǎn)單的數(shù)據(jù)采集功能。在發(fā)布展示會(huì)上,發(fā)生了這樣的對(duì)話…… 開發(fā)者:這是我們的第一個(gè)功能。我們從文本文件、Excel 數(shù)據(jù)表和遺留數(shù)據(jù)庫(kù)采集數(shù)據(jù),現(xiàn)在我們的數(shù)據(jù)庫(kù)中有這些數(shù)據(jù)……(展示數(shù)據(jù)庫(kù)結(jié)構(gòu)) 想想這個(gè)客戶會(huì)怎么定義一個(gè)“成功的軟件項(xiàng)目”?好吧,也許這個(gè)項(xiàng)目超過了預(yù)期的時(shí)間,也許投入了更多的人力,但這些并不意味著“項(xiàng)目失敗”——只是付出更高的成本。關(guān)鍵在于,他投入的這些成本能夠帶來多大的收益,他的投資回報(bào)率是否劃算。對(duì)于這個(gè)客戶而言,如果項(xiàng)目能夠隨時(shí)給他提供可用的、能夠創(chuàng)造最大價(jià)值的軟件,能夠隨時(shí)讓——就像故事中提到的——這種有價(jià)值的想法得以實(shí)現(xiàn),這就是一個(gè)成功的項(xiàng)目。 所以,親愛的讀者,請(qǐng)你忘記本文標(biāo)題上出現(xiàn)的“敏捷”二字,我們?cè)谶@里所說的不是別的,就是一種為客戶創(chuàng)造最大化價(jià)值的軟件開發(fā)方法。這樣的方法有很多種,但它們有一個(gè)共同的特點(diǎn):盡快、盡可能頻繁地交付可以工作的軟件,讓客戶盡快開始使用軟件,從使用中創(chuàng)造價(jià)值、厘清思路、提出反饋。仍然以 ThoughtWorks 的項(xiàng)目為例,這些項(xiàng)目通常在啟動(dòng)開發(fā)階段之后一個(gè)月內(nèi)就會(huì)發(fā)布第一個(gè)版本,隨后每一周或每?jī)芍馨l(fā)布一個(gè)新版本——每個(gè)版本都是一個(gè)可以工作的軟件,每個(gè)版本都比前一個(gè)版本具有更豐富的功能,并且每個(gè)版本都包含客戶認(rèn)為迄今為止最有價(jià)值的那些功能。用軟件開發(fā)的“黑話”,“開發(fā)下一個(gè)版本”的過程叫做“迭代”,這些開發(fā)方法最大的共同點(diǎn)就是“迭代式開發(fā)”——不是一股腦地交付全部功能,而是每次增加一點(diǎn)、漸進(jìn)地交付最有價(jià)值的功能。 軟件開發(fā)的夢(mèng)想與真實(shí) 回到文章開始處的兩個(gè)故事。我曾經(jīng)說過,對(duì)于很多軟件企業(yè)而言,項(xiàng)目 A 是一個(gè)“理想的”成功項(xiàng)目。那么,是什么讓情況變得不那么理想? 答案是一個(gè)所有軟件開發(fā)者耳熟能詳?shù)脑~:需求變更。在真實(shí)的項(xiàng)目中,客戶通常不會(huì)等到最后一天再照單全收整個(gè)項(xiàng)目,因?yàn)樗雷约旱臉I(yè)務(wù)正在發(fā)生變化。這時(shí)需求變更就出現(xiàn)了,伴隨著來回的扯皮和討價(jià)還價(jià)。更糟的是,大量的需求變更發(fā)生在項(xiàng)目晚期——因?yàn)橹钡竭@時(shí)客戶才真正看到、使用到這個(gè)軟件,他的很多想法才真正浮現(xiàn)成型。隨著這種“最后一分鐘的需求變更”,項(xiàng)目超期、超出預(yù)算也就成了家常便飯。能夠像項(xiàng)目A這樣完工交付的,實(shí)在是鳳毛麟角的幸運(yùn)兒。 為了對(duì)付需求變更這個(gè)噩夢(mèng),軟件開發(fā)者們還發(fā)明了另一個(gè)詞:變更控制。這個(gè)有趣的詞暗示著:需求變更是一種“不好”的東西,是需要“控制”的東西。然而站在客戶的角度上想想,他在親身使用了軟件之后提出的要求,難道不是最有價(jià)值的東西嗎?把這種真正創(chuàng)造業(yè)務(wù)價(jià)值的要求“控制”起來,難道是合理的嗎? 在前面我也暗示過,并非所有的客戶都一定青睞迭代式開發(fā)。那么,哪些軟件項(xiàng)目不一定需要迭代式開發(fā)呢?從整篇文章的內(nèi)容不難看出,如果客戶的業(yè)務(wù)絕對(duì)不會(huì)變化,如果客戶的需求巨細(xì)靡遺非常明確,如果客戶不需要盡快開始使用軟件以便收回成本,那么迭代式開發(fā)對(duì)他的幫助就會(huì)小得多。不過,如果讀者認(rèn)真思考的話,這樣的例子也許并不多——也許比你最初認(rèn)為的要少得多。一個(gè)很好的例子是“神州六號(hào)”火箭使用的計(jì)算機(jī)控制系統(tǒng)。還有多少這樣的例子?讀者不妨試著自己想想。 如果我足夠幸運(yùn)的話,也許一些讀者已經(jīng)被這篇文章吊起了胃口:既然有這么好的軟件開發(fā)方法,既然它能夠?yàn)槲覀儎?chuàng)造更大的價(jià)值,那還等什么呢,我們馬上就動(dòng)手吧。事情不會(huì)那么簡(jiǎn)單。為了讓迭代式開發(fā)能夠成為現(xiàn)實(shí),為了確保盡快、盡可能頻繁地交付,為了確保每次交付的都是最有價(jià)值的功能,我們——包括軟件開發(fā)者、軟件企業(yè)和客戶——需要很多的改變。這里既有職責(zé)與權(quán)利的劃分,也有開發(fā)過程和團(tuán)隊(duì)的重組,還有技術(shù)層面的實(shí)踐指導(dǎo)。這些正是敏捷方法學(xué)所涵蓋的內(nèi)容。缺少了這些東西,“為客戶創(chuàng)造最大價(jià)值”就只能成為一句空話。在后續(xù)的文章里,我們將結(jié)合 ThoughtWorks 的實(shí)踐經(jīng)驗(yàn),逐步介紹敏捷方法的方方面面。
posted @ 2008-06-15 15:35 JavaSuns 閱讀(312) | 評(píng)論 (0) | 編輯 收藏 java與C#區(qū)別(轉(zhuǎn))最開始時(shí)微軟公司將Java當(dāng)做一種能解決C和C++中存在的問題的語言,并不在意,并繼續(xù)維持和培訓(xùn)著其C和C++技術(shù)和編程人員。接下來不幸的是,正當(dāng)微軟盡力在Visual J++基礎(chǔ)上拓展Java功能,并使之與Windows操作系統(tǒng)緊密結(jié)合在一起的時(shí)候,Sun公司對(duì)微軟提出法律訴訟說其違反了許可證協(xié)議中的條款,最終的結(jié)果是微軟公司不得不停止其Visual J++產(chǎn)品的開發(fā)。(微軟公司仍然銷售Visual J++,但是從1998年10月以來就沒有新的版本發(fā)布,并且在.Net平臺(tái)上也沒有Visual J++的位置了)接下來的事情就很清楚了,微軟公司開發(fā)了C#語言。接下來的一部分將討論C#與Java的相似性。
C#與Java的區(qū)別 C#最引人的地方是它與Java的區(qū)別而不是其相似性。下面主要來介紹C#區(qū)別于Java的不同的運(yùn)行特點(diǎn)及Java完全沒有的特點(diǎn)。 中間語言 當(dāng)MSIL被編譯成最終的機(jī)器碼時(shí),微軟公司在如何選擇上是非常靈活的。微軟公司很謹(jǐn)慎的對(duì)外宣稱說MSIL不是解釋型的,而是被編譯成機(jī)器碼。因?yàn)殚_發(fā)人員都有這樣一個(gè)觀念:Java程序天生就比C程序運(yùn)行慢,所以這暗示著基于MSIL的程序優(yōu)于解釋型的Java字節(jié)碼。當(dāng)然,既然C#和其它MSIL產(chǎn)品編譯器還未發(fā)布,那么這一點(diǎn)就還未證明,但是Java無處不在的即時(shí)編譯器使得C#和Java在效能上是一樣的。象“C#是編譯型的,Java是解釋型的”這樣話只是銷售中的技巧。Java的字節(jié)碼和MSIL碼都是的類似匯編的中間語言,在運(yùn)行時(shí)執(zhí)行這些中間碼。 與COM的整合 對(duì)于基于Windows的C#開發(fā)人員來說,最大的收獲是對(duì)COM的無損整合,COM是微軟Win32的組件技術(shù)。實(shí)際上,任何一種.Net體系結(jié)構(gòu)上的語言最終都可能去寫COM的客戶端和服務(wù)器端程序。用C#編寫的類也會(huì)作為COM組件的子類;結(jié)果類(resulting class)也能作為COM組件使用,并作為COM組件的子類。 微軟公司的目標(biāo)是使越來越多的語言都能訪問組件,并使這些組件能整合到.Net體系結(jié)構(gòu)中。已有幾個(gè)廠商開始著手開發(fā)支持.Net功能的編程語言,如COBOL和Haskell。開發(fā)人員能選擇不同的語言解決不同問題,更重要的是,開發(fā)人員不必為采用.Net體系結(jié)構(gòu)而必須學(xué)習(xí)新語言,可以選擇一種他們熟悉的語言。 總結(jié) 本文的第一、二部分對(duì)C#做了一膚淺的總體介紹,主要是其產(chǎn)生動(dòng)機(jī)及與Java的相似性。第三部分則涵概了C#的語言特點(diǎn)。用范例說明了C#與Java兩者在相似性外,它們又是非常不同的,有許多細(xì)微的語義和設(shè)計(jì)區(qū)別,適合不同的技術(shù)和市場(chǎng)環(huán)境,又談到了微軟公司對(duì)C#進(jìn)行標(biāo)準(zhǔn)化方面的嘗試,及其對(duì)Java的影響。 c#與java的區(qū)別
1.屬性: java中定義和訪問均要用get和set方法,可以不成對(duì)出現(xiàn)。 c#中是真正的屬性,定義時(shí)get和set必須同時(shí)出現(xiàn),房問時(shí)用.號(hào)即可。不用get,set 2.對(duì)象索引 就是對(duì)象數(shù)組 public Story this [int index] { 3.C#中,不用任何范圍修飾符時(shí),默認(rèn)的是protect,因而不能在類外被訪問. 4.因?yàn)镴AVA規(guī)定,在一個(gè)文件中只能有一個(gè)public類,而且這個(gè)類的名稱必須與文件名一模一樣,這是一個(gè)區(qū)別 5.在C#中,它是以Main方法來定位入口的.如果一個(gè)程序中沒有一個(gè)名為Main的方法,就會(huì)出"找不到入口的錯(cuò)誤".不要把Main寫成main喲 6.C#預(yù)定義的簡(jiǎn)單數(shù)據(jù)類型比Java多。例如,C#有unit,即無符號(hào)整數(shù) 7.忘掉Java中的static final修飾符。在C#中,常量可以用const關(guān)鍵詞聲明 C#的設(shè)計(jì)者還增加了readonly關(guān)鍵詞,readonly域只能通過初始化器或類的構(gòu)造函數(shù)設(shè)置 8.公用類的入口點(diǎn):c#是可以對(duì)Main進(jìn)行重載(java中是main),允許有int返回值和空參數(shù)的Main 9.在Java中,switch語句只能處理整數(shù)。但C#中的switch語句不同,它還能夠處理字符變量。請(qǐng)考慮下面用switch語句處理字符串變量的C#代碼 10.C#沒有>>>移位操作符 11.goto關(guān)鍵詞: Java不用goto關(guān)鍵詞。在C#中,goto允許你轉(zhuǎn)到指定的標(biāo)簽。不過,C#以特別謹(jǐn)慎的態(tài)度對(duì)待goto,比如它不允許goto轉(zhuǎn)入到語句塊的內(nèi)部。在Java中,你可以用帶標(biāo)簽的語句加上break或continue取代C#中的goto。 12.int[] x = { 0, 1, 2, 3 }; int x[] = { 0, 1, 2, 3 }; 但在C#中,只有第一行代碼合法,[]不能放到變量名字之后。 13.與Java不同的是,C#允許為名稱空間或者名稱空間中的類指定別名: using TheConsole = System.Console; 14.在Java中,包的名字同時(shí)也是實(shí)際存在的實(shí)體,它決定了放置.java文件的目錄結(jié)構(gòu)。在C#中,物理的包和邏輯的名稱之間是完全分離的 .NET中包的實(shí)體稱為程序集(Assembly)。每一個(gè)程序集包含一個(gè)manifest結(jié)構(gòu)。manifest列舉程序集所包含的文件,控制哪些類型和資源被顯露到程序集之外,并把對(duì)這些類型和資源的引用映射到包含這些類型與資源的文件。程序集是自包含的,一個(gè)程序集可以放置到單一的文件之內(nèi),也可以分割成多個(gè)文件。.NET的這種封裝機(jī)制解決了DLL文件所面臨的問題,即臭名昭著的DLL Hell問題。 15.在Java中,java.lang包是默認(rèn)的包,C#中不存在默認(rèn)的包 16.C#中的訪問修飾符與Java中的基本對(duì)應(yīng),但多出了一個(gè)internal。簡(jiǎn)而言之,C#有5種類型的可訪問性,如下所示: public:成員可以從任何代碼訪問。 protected:成員只能從派生類訪問。 internal:成員只能從同一程序集的內(nèi)部訪問。 protected internal:成員只能從同一程序集內(nèi)的派生類訪問。 private:成員只能在當(dāng)前類的內(nèi)部訪問。 17.由于C#中不存在final關(guān)鍵詞,如果想要某個(gè)類不再被派生,你可以使用sealed關(guān)鍵詞 18.與Java不同,C#中的接口不能包含域(Field)。 另外還要注意,在C#中,接口內(nèi)的所有方法默認(rèn)都是公用方法。在Java中,方法聲明可以帶有public修飾符(即使這并非必要),但在C#中,顯式為接口的方法指定public修飾符是非法的。例如,下面的C#接口將產(chǎn)生一個(gè)編譯錯(cuò)誤。 19.C#中的is操作符與Java中的instanceof操作符一樣,兩者都可以用來測(cè)試某個(gè)對(duì)象的實(shí)例是否屬于特定的類型。在Java中沒有與C#中的as操作符等價(jià)的操作符。as操作符與is操作符非常相似,但它更富有“進(jìn)取心”:如果類型正確的話,as操作符會(huì)嘗試把被測(cè)試的對(duì)象引用轉(zhuǎn)換成目標(biāo)類型;否則,它把變量引用設(shè)置成null。 20.C#仍舊保留了C++的內(nèi)存手工管理方法,它適合在速度極端重要的場(chǎng)合使用,而在Java中這是不允許的 21.在C#中,所有的異常都從一個(gè)名為Exception的類派生 22.枚舉器即enum類型(java無),把它作為一個(gè)變量值的類型使用,從而把變量可能的取值范圍限制為枚舉器中出現(xiàn)的值。 23.結(jié)構(gòu)(Struct)與類很相似,而結(jié)構(gòu)是一種值類型,它存儲(chǔ)在棧中或者是嵌入式的,結(jié)構(gòu)可以實(shí)現(xiàn)接口,可以象類一樣擁有成員,但結(jié)構(gòu)不支持繼承 24.屬性聲明語法的第一部分與域聲明很相似,第二部分包括一個(gè)set過程和/或一個(gè)get過程 25.傳值方式: 在java中簡(jiǎn)單數(shù)據(jù)類型的值傳參時(shí),都以傳值方式; 在c#中如果加ref則會(huì)以引用的方式傳值(方法內(nèi)部改變?cè)搮?shù),則外部變量一起跟著變); 加out與ref基本相同,但out不要求參數(shù)一定要初始化. 26.c#保留了指針。unsafe 27.代理:代理(delegate)可以看作C++或者其他語言中的函數(shù)指針 代理用來封裝可調(diào)用方法。你可以在類里面編寫方法并在該方法上創(chuàng)建代理,此后這個(gè)代理就可以被傳遞到第二個(gè)方法。這樣,第二個(gè)方法就可以調(diào)用第一個(gè)方法。 代理是從公共基類System.Delegate派生的引用類型。定義和使用代理包括三個(gè)步驟:聲明,創(chuàng)建實(shí)例,調(diào)用。代理用delegate聲明語法聲明。 posted @ 2008-06-15 14:37 JavaSuns 閱讀(918) | 評(píng)論 (0) | 編輯 收藏 |
|