|
2018年10月26日
2009年6月13日
package cc.dynasoft.struts.action;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFFooter;
import org.apache.poi.hssf.usermodel.HSSFHeader;
import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;
import cc.dynasoft.bean.Department;
///import org.apache.poi.hssf.record.HeaderRecorder;
public class OutputExcel {
public static boolean outputExcel(ExcelArgs args, List title, List list) {
try {
int cellNum = args.getCellNum(); // workbook
int rowNum = args.getRowNum();
/**
* 建立表格設置。
*/
HSSFWorkbook wb = new HSSFWorkbook(); // create the new Workbook
HSSFSheet sheet = wb.createSheet(args.getSheetName()); // create
/**
* 打印設置
*/
HSSFPrintSetup hps = sheet.getPrintSetup();
hps.setPaperSize((short) 9); // 設置A4紙
// hps.setLandscape(true); // 將頁面設置為橫向打印模式
sheet.setHorizontallyCenter(true); // 設置打印頁面為水平居中
// sheet.setVerticallyCenter(true); // 設置打印頁面為垂直居中
wb.setPrintArea(0, "$A$2:$e$" + rowNum + 2);// 打印區域設置.
/**
* 設置表的Footer
*/
HSSFFooter footer = sheet.getFooter();
// 設置footer的位置和顯示的內容
footer.setCenter("Time:" + HSSFFooter.date());
footer.setRight("Page " + HSSFFooter.page() + " of "
+ HSSFFooter.numPages());
/**
* 設置表的Header
*/
// 設置header的位置,共有三種位置和相應的顯示設置
HSSFHeader header = sheet.getHeader();
// header.setRight("Center Header");
// header.setLeft("Left Header");
header.setCenter(HSSFHeader.font("Stencil-Normal", "Italic")
+ HSSFHeader.fontSize((short) 30) + args.getHeaderTitle());
// header.endDoubleUnderline();
header.startUnderline();
/**
* 設置列的寬度
*/
sheet.setColumnWidth((short) 2,
(short) ((30 * 8) / ((double) 1 / 10)));
sheet.setColumnWidth((short) 3,
(short) ((40 * 8) / ((double) 1 / 10)));
sheet.setColumnWidth((short) 4,
(short) ((50 * 8) / ((double) 1 / 20)));
/**
* 創建第一行,也就是顯示的標題, 可以高置的高度,單元格的格式,顏色,字體等設置. 同時可以合并單元格.
*/
HSSFRow row0 = sheet.createRow(0); // 創建0行
row0.setHeight((short) 0x300); // 設直行的高度.
HSSFFont font2 = wb.createFont(); // 創建字體格式
font2.setColor(HSSFFont.SS_NONE); // 設置單元格字體的顏色.
font2.setFontHeight((short) 700); // 設置字體大小
font2.setFontName("Courier New"); // 設置單元格字體
HSSFCell cell0 = row0.createCell((short) 0); // 創建0行0列.
HSSFCellStyle style3 = wb.createCellStyle(); // 創建單元格風格.
style3.setAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
style3.setAlignment(HSSFCellStyle.ALIGN_CENTER); // /水平居中
style3.setFont(font2); // 將字體格式加入到單元格風格當中
// cell0.setCellType()
cell0.setCellStyle(style3); // 設置單元格的風格.
cell0.setCellValue(args.getHeaderTitle()); // 設置單元的內容.
sheet.addMergedRegion(new Region(0, (short) 0, 0,
(short) (cellNum - 1)));// 指定合并區域,前二個參數為開始處X,Y坐標.后二個為結束的坐標.
/**
* 設置其它數據 設置風格
*/
HSSFCellStyle style = wb.createCellStyle();
style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 設置單無格的邊框為粗體
style.setBottomBorderColor(HSSFColor.BLACK.index); // 設置單元格的邊框顏色.
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setLeftBorderColor(HSSFColor.BLACK.index);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setRightBorderColor(HSSFColor.BLACK.index);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
style.setTopBorderColor(HSSFColor.BLACK.index);
// style.setWrapText(true);//文本區域隨內容多少自動調整
// style.setFillForegroundColor(HSSFColor.LIME.index);
// style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
/**
* 設置風格1
*/
HSSFCellStyle style1 = wb.createCellStyle();
style1.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 設置單無格的邊框為粗體
style1.setBottomBorderColor(HSSFColor.BLACK.index); // 設置單元格的邊框顏色.
style1.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style1.setLeftBorderColor(HSSFColor.BLACK.index);
style1.setBorderRight(HSSFCellStyle.BORDER_THIN);
style1.setRightBorderColor(HSSFColor.BLACK.index);
style1.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
style1.setTopBorderColor(HSSFColor.BLACK.index);
style1.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);// 最好的設置Pattern
// 單元格背景的顯示模式.
style1.setFillForegroundColor(new HSSFColor.RED().getIndex()); // 設置單元格背景色;
style1.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平對齊方式
// style1.setWrapText(true);//文本區域隨內容多少自動調整
// style.setFillPattern(HSSFCellStyle.//);
// 設置字體Color,首先創建Font對象,后對font設置,然后做為參數傳給style
HSSFFont font = wb.createFont();
font.setColor(HSSFFont.SS_NONE);
// font.setFontHeightInPoints((short)24);
font.setFontName("Courier New");
// font.setItalic(true);
// font.setStrikeout(true);//給字體加上刪除線
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
style1.setFont(font);
/**
*
* 設置第零行表格說明行
*
*
*
*/
HSSFRow row1 = sheet.createRow((short) 1);
for (int j = 0; j < cellNum; j++) {
HSSFCell cell = row1.createCell((short) j);
cell.setCellValue((String) title.get(j));
cell.setCellStyle(style1);
}
// style.setFillPattern(HSSFCellStyle.NO_FILL);
/**
* 設置表的內容主體
*/
Iterator iter = list.iterator();
for (int i = 2; iter.hasNext(); i++) {
Department dep = (Department) iter.next();
HSSFRow row = sheet.createRow((short) i);
HSSFCell cell5 = row.createCell((short) 0);
HSSFCell cell1 = row.createCell((short) 1);
HSSFCell cell2 = row.createCell((short) 2);
HSSFCell cell3 = row.createCell((short) 3);
HSSFCell cell4 = row.createCell((short) 4);
cell5.setCellValue(dep.getId());
cell5.setCellStyle(style);
cell1.setCellValue(dep.getParentId());
cell1.setCellStyle(style);
cell2.setCellValue(dep.getName());
cell2.setCellStyle(style);
cell3.setCellValue(dep.getDescription());
cell3.setCellStyle(style);
cell4.setCellValue(dep.getImagePath());
cell4.setCellStyle(style);
}
// Write the output to a file}
// FileOutputStream fileOut = new
// FileOutputStream(args.getPath()+args.getFileName());
/**
* 對文件進行輸出操作。
*/
FileOutputStream fileOut = new FileOutputStream(args
.getPathAndName());
wb.write(fileOut);
// fileOut.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
return true;
}
}
2008年7月28日
mkdir /home/u1 創建文件夾/home/u1
chown oracle /home/u1 表示改變目錄所有者為oracle賬戶;
chgrp dba /home/u1 改變/home/u1目錄為dba所有;
chmod 755 /home/u1 表示oracle賬戶對/home/u1目錄有755權限;
rmdir /home/u1 表示刪除/home/u1目錄
hostname可以查看linux的計算機名;
whoami可以查看當前用戶;
pwd顯示當前路徑;
df查看系統的硬件信息
ls -lrt l表示顯示詳細列表,-t表示按時間排序,-r反向排序
cat orcl_ora_3436.trc|grep bucket
以下查看相關文件內容:
more /etc/oratab
cat /etc/passwd
cat /etc/group
copy命令
該命令的功能是將給出的文件或目錄拷貝到另一文件或目錄中,同MSDOS下的copy命令一樣,功能十分強大。
語法: cp [選項] 源文件或目錄 目標文件或目錄
說明:該命令把指定的源文件復制到目標文件或把多個源文件復制到目標目錄中。
該命令的各選項含義如下:
- a 該選項通常在拷貝目錄時使用。它保留鏈接、文件屬性,并遞歸地拷貝目錄,其作用等于dpR選項的組合。
- d 拷貝時保留鏈接。
- f 刪除已經存在的目標文件而不提示。
- i 和f選項相反,在覆蓋目標文件之前將給出提示要求用戶確認。回答y時目標文件將被覆蓋,是交互式拷貝。
- p 此時cp除復制源文件的內容外,還將把其修改時間和訪問權限也復制到新文件中。
- r 若給出的源文件是一目錄文件,此時cp將遞歸復制該目錄下所有的子目錄和文件。此時目標文件必須為一個目錄名。
- l 不作拷貝,只是鏈接文件。
需要說明的是,為防止用戶在不經意的情況下用cp命令破壞另一個文件,如用戶指定的目標文件名已存在,用cp命令拷貝文件后,這個文件就會被新源文件覆蓋,因此,建議用戶在使用cp命令拷貝文件時,最好使用i選項。
2008年6月26日
對于rownum來說它是oracle系統順序分配為從查詢返回的行的編號,返回的第一行分配的是1,第二行是2,依此類推,這個偽字段可以用于限制查詢返回的總行數,而且rownum不能以任何表的名稱作為前綴。
舉例說明:
例如表:student(學生)表,表結構為:
ID char(6) --學號
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 對于等于某值的查詢條件
如 果希望找到學生表中第一條學生的信息,可以使用rownum=1作為條件。但是想找到學生表中第二條學生的信息,使用rownum=2結果查不到數據。因 為rownum都是從1開始,但是1以上的自然數在rownum做等于判斷是時認為都是false條件,所以無法查到rownum = n(n>1的自然數)。
SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回記錄條數的地方,保證不出錯,如:隱式游標)
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對于大于某值的查詢條件
如果想找到從第二行記錄以后的記錄,當使用rownum>2是查不出記錄的,原因是由于rownum是一個總是從1開始的偽列,Oracle 認為rownum> n(n>1的自然數)這種條件依舊不成立,所以查不到記錄
SQL> select rownum,id,name from student where rownum >2;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
那如何才能找到第二行以后的記錄呀。可以使用以下的子查詢方法來解決。注意子查詢中的rownum必須要有別名,否則還是不會查出記錄來,這是因為rownum不是某個表的列,如果不起別名的話,無法知道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對于小于某值的查詢條件
如果想找到第三條記錄以前的記錄,當使用rownum<3是能得到兩條記錄的。顯然rownum對于rownum<n((n>1的自然數)的條件認為是成立的,所以可以找到記錄。
SQL> select rownum,id,name from student where rownum <3;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
1 200001 張一
2 200002 王二
綜 上幾種情況,可能有時候需要查詢rownum在某區間的數據,那怎么辦呀從上可以看出rownum對小于某值的查詢條件是人為true的,rownum對 于大于某值的查詢條件直接認為是false的,但是可以間接的讓它轉為認為是true的。那就必須使用子查詢。例如要查詢rownum在第二行到第三行之 間的數據,包括第二行和第三行數據,那么我們只能寫以下語句,先讓它返回小于等于三的記錄行,然后在主查詢中判斷新的rownum的別名列大于等于二的記 錄行。但是這樣的操作會在大數據集中影響速度。
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的是在取數據的時候產生的序號,所以想對指定排序的數據去指定的rowmun行數據就必須注意了。
SQL> select rownum ,id,name from student order by name;
ROWNUM ID NAME
---------- ------ ---------------------------------------------------
3 200003 李三
2 200002 王二
1 200001 張一
4 200004 趙四
可以看出,rownum并不是按照name列來生成的序號。系統是按照記錄插入時的順序給記錄排的號,rowid也是順序分配的。為了解決這個問題,必須使用子查詢
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標出正確序號(有小到大)
2008年6月25日
//ArrayList
{
ArrayList arraylist=new ArrayList();
arraylist.add(0,"end");//指定索引加入值
//需注意的是,如果現有2個值,我加入索引為5的那么就會出現異常
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);//打印數組的長度
}
//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的數據進list
System.out.println("\n"+list);
Collections.swap(list,2,1);//調換索引為1和2的元素的位置
System.out.println(list);
}
//EventObject
{
String s="hello";
String s2=s;
EventObject eventobject=new EventObject(s);//一個準容器類型,確切的歸類它不是容器
System.out.println("EventObject:");
System.out.println(eventobject.getSource());
System.out.println(eventobject.equals(s2));
}
//HashMap
{
HashMap hashmap=new HashMap();//一個速度最快的容器
hashmap.put("0","c");
hashmap.put("1","a");
hashmap.put("2","b");
hashmap.put("3","a");
System.out.println("HashMap:");
System.out.println(hashmap);//該容器有其內部的排序方式
Set set=hashmap.keySet();//獲取全部鍵
Iterator iterator=set.iterator();
while(iterator.hasNext()){
System.out.print(hashmap.get(iterator.next())+";");
}
}
//HashSet
{
HashSet hashset=new HashSet();//一個絕對不能重復的類型
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();//一個完全可以由其他容器替換的老容器類型
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已經不是主流,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"));//是否包含這個鍵
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"));//是否包含這個鍵
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"));//是否包含對象
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();//刪除第一個元素
//linkedlist.removeLast();//刪除最后一個元素
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()+";");
}
//后進先出
System.out.println("\n"+stack.peek());
System.out.println(stack.pop());
System.out.println(stack.contains("d")+";"+stack.contains("a"));//是否包含該元素,有趣的事情發生了
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:");//可以對鍵排序
System.out.println(treemap);
System.out.println(treemap.firstKey());//返回第一個鍵
Set set=treemap.keySet();
Iterator iterator=set.iterator();
while(iterator.hasNext()){
System.out.print(treemap.get(iterator.next())+";");
}
}
//TreeSet
{
TreeSet treeset=new TreeSet();//自動排序內容
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());//返回第一個元素
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);//重新設置大小為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");//刪除該鍵對應的值
//weakhashmap.get("1");//獲取指定鍵的值
}
}
在JAVA的util包中有兩個所有集合的父接口Collection和Map,它們的父子關系:
java.util
+Collection 這個接口extends自 --java.lang.Iterable接口
+List 接口
-ArrayList 類
-LinkedList 類
-Vector 類 此類是實現同步的
+Queue 接口
+不常用,在此不表.
+Set 接口
+SortedSet 接口
-TreeSet 類
-HashSet
+Map 接口
-HashMap 類 (除了不同步和允許使用 null 鍵/值之外,與 Hashtable 大致相同.)
-Hashtable 類 此類是實現同步的,不允許使用 null 鍵值
+SortedMap 接口
-TreeMap 類
以下對眾多接口和類的簡單說明:首先不能不先說一下數組(Array)
一、Array , Arrays
Java所有“存儲及隨機訪問一連串對象”的做法,array是最有效率的一種。
1、
效率高,但容量固定且無法動態改變。
array還有一個缺點是,無法判斷其中實際存有多少元素,length只是告訴我們array的容量。
2、Java中有一個Arrays類,專門用來操作array。
arrays中擁有一組static函數,
equals():比較兩個array是否相等。array擁有相同元素個數,且所有對應元素兩兩相等。
fill():將值填入array中。
sort():用來對array進行排序。
binarySearch():在排好序的array中尋找元素。
System.arraycopy():array的復制。
二、Collection , Map
若撰寫程序時不知道究竟需要多少對象,需要在空間不足時自動擴增容量,則需要使用容器類庫,array不適用。
1、Collection 和 Map 的區別
容器內每個為之所存儲的元素個數不同。
Collection類型者,每個位置只有一個元素。
Map類型者,持有 key-value pair,像個小型數據庫。
2、Java2容器類類庫的用途是“保存對象”,它分為兩類,各自旗下的子類關系
Collection
--List:將以特定次序存儲元素。所以取出來的順序可能和放入順序不同。
--ArrayList / LinkedList / Vector
--Set : 不能含有重復的元素
--HashSet /TreeSet
Map
--HashMap
--HashTable
--TreeMap
Map----一組成對的“鍵值對”對象,即其元素是成對的對象,最典型的應用就是數據字典,并且還有其它廣泛的應用。另外,Map可以返回其所有鍵組成的Set和其所有值組成的Collection,或其鍵值對組成的Set,并且還可以像數組一樣擴展多維Map,只要讓Map中鍵值對的每個“值”是一個Map即可。
Collection下 1.迭代器
迭代器是一種設計模式,它是一個對象,它可以遍歷并選擇序列中的對象,而開發人員不需要了解該序列的底層結構。迭代器通常被稱為“輕量級”對象,因為創建它的代價小。
Java中的Iterator功能比較簡單,并且只能單向移動:
(1) 使用方法iterator()要求容器返回一個Iterator。第一次調用Iterator的next()方法時,它返回序列的第一個元素。注意:iterator()方法是java.lang.Iterable接口,被Collection繼承。
(2) 使用next()獲得序列中的下一個元素。
(3) 使用hasNext()檢查序列中是否還有元素。
(4) 使用remove()將迭代器新返回的元素刪除。
Iterator是Java迭代器最簡單的實現,為List設計的ListIterator具有更多的功能,它可以從兩個方向遍歷List,也可以從List中插入和刪除元素。
2.List的功能方法
List(interface): 次序是List最重要的特點;它確保維護元素特定的順序。List為Collection添加了許多方法,使得能夠向List中間插入與移除元素(只推薦LinkedList使用)。一個List可以生成ListIterator,使用它可以從兩個方向遍歷List,也可以從List中間插入和刪除元素。
ArrayList: 由數組實現的List。它允許對元素進行快速隨機訪問,但是向List中間插入與移除元素的速度很慢。ListIterator只應該用來由后向前遍歷ArrayList,而不是用來插入和刪除元素,因為這比LinkedList開銷要大很多。
LinkedList: 由列表實現的List。對順序訪問進行了優化,向List中間插入與刪除得開銷不大,隨機訪問則相對較慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),這些方法(沒有在任何接口或基類中定義過)使得LinkedList可以當作堆棧、隊列和雙向隊列使用。
3.Set的功能方法
Set(interface): 存入Set的每個元素必須是唯一的,這也是與List不同的,因為Set不保存重復元素。加入Set的Object必須定義equals()方法以確保對象的唯一性。Set與Collection有完全一樣的接口。Set接口不保證維護元素的次序。
HashSet: HashSet能快速定位一個元素,存入HashSet的對象必須定義hashCode()。
TreeSet: 保持次序的Set,底層為樹結構。使用它可以從Set中提取有序的序列。
LinkedHashSet: 具有HashSet的查詢速度,且內部使用鏈表維護元素的順序(插入的次序)。于是在使用迭代器遍歷Set時,結果會按元素插入的次序顯示。
HashSet采用散列函數對元素進行排序,這是專門為快速查詢而設計的;TreeSet采用紅黑樹的數據結構進行排序元素;LinkedHashSet內部使用散列以加快查詢速度,同時使用鏈表維護元素的次序,使得看起來元素是以插入的順序保存的。需要注意的是,生成自己的類時,Set需要維護元素的存儲順序,因此要實現Comparable接口并定義compareTo()方法。
3、其他特征
* List,Set,Map將持有對象一律視為Object型別。
* Collection、List、Set、Map都是接口,不能實例化。
繼承自它們的 ArrayList, Vector, HashTable, HashMap是具象class,這些才可被實例化。
* vector容器確切知道它所持有的對象隸屬什么型別。vector不進行邊界檢查。
三、Collections
Collections是針對集合類的一個幫助類。提供了一系列靜態方法實現對各種集合的搜索、排序、線程完全化等操作。
相當于對Array進行類似操作的類——Arrays。
如,Collections.max(Collection coll); 取coll中最大的元素。
Collections.sort(List list); 對list中元素排序
四、如何選擇?
1、容器類和Array的區別、擇取
* 容器類僅能持有對象引用(指向對象的指針),而不是將對象信息copy一份至數列某位置。
* 一旦將對象置入容器內,便損失了該對象的型別信息。
2、
* 在各種Lists中,最好的做法是以ArrayList作為缺省選擇。當插入、刪除頻繁時,使用LinkedList();
Vector總是比ArrayList慢,所以要盡量避免使用。
* 在各種Sets中,HashSet通常優于HashTree(插入、查找)。只有當需要產生一個經過排序的序列,才用TreeSet。
HashTree存在的唯一理由:能夠維護其內元素的排序狀態。
* 在各種Maps中
HashMap用于快速查找。
* 當元素個數固定,用Array,因為Array效率是最高的。
結論:最常用的是ArrayList,HashSet,HashMap,Array。而且,我們也會發現一個規律,用TreeXXX都是排序的。
注意:
1、Collection沒有get()方法來取得某個元素。只能通過iterator()遍歷元素。
2、Set和Collection擁有一模一樣的接口。
3、List,可以通過get()方法來一次取出一個元素。使用數字來選擇一堆對象中的一個,get(0)...。(add/get)
4、一般使用ArrayList。用LinkedList構造堆棧stack、隊列queue。
5、Map用 put(k,v) / get(k),還可以使用containsKey()/containsValue()來檢查其中是否含有某個key/value。
HashMap會利用對象的hashCode來快速找到key。
* hashing
哈希碼就是將對象的信息經過一些轉變形成一個獨一無二的int值,這個值存儲在一個array中。
我們都知道所有存儲結構中,array查找速度是最快的。所以,可以加速查找。
發生碰撞時,讓array指向多個values。即,數組每個位置上又生成一個梿表。
6、Map中元素,可以將key序列、value序列單獨抽取出來。
使用keySet()抽取key序列,將map中的所有keys生成一個Set。
使用values()抽取value序列,將map中的所有values生成一個Collection。
為什么一個生成Set,一個生成Collection?那是因為,key總是獨一無二的,value允許重復。
2008年6月15日
1、項目經理必須關注項目成功的三個標準
簡單地說,一是準時;二是預算控制在既定的范圍內;三是質量得到經理和用戶們的贊許。項目經理必須保證項目小組的每一位成員都能對照上面三個標準來進行工作。
2、任何事都應當先規劃再執行
就項目管理而言,很多專家和實踐人員都同意這樣一個觀點:需要項目經理投入的最重要的一件事就是規劃。只有詳細而系統的由項目小組成員參與的規劃才是項目成功的唯一基礎。當現實的世界出現了一種不適于計劃生存的環境時,項目經理應制定一個新的計劃來反映環境的變化。規劃、規劃、再規劃就是項目經理的一種生活方式。
3、項目經理必須以自己的實際行動向項目小組成員傳遞一種緊迫感
由于項目在時間、資源和經費上都是有限的,項目最終必須完成。但項目小組成員大多有自己的愛好,項目經理應讓項目小組成員始終關注項目的目標和截止期限。例如,可以定期檢查,可以召開例會,可以制作一些提醒的標志置于項目的場所。
4、成功的項目應使用一種可以度量且被證實的項目生命周期
標準的信息系統開發模型可以保證專業標準和成功的經驗能夠融入項目計劃。這類模型不僅可以保證質量,還可以使重復勞動降到最低程度。因此,當遇到時間和預算壓力需要削減項目時,項目經理應確定一種最佳的項目生命周期。
5、所有項目目標和項目活動必須生動形象地得以交流和溝通
項目經理和項目小組在項目開始時就應當形象化地描述項目的最終目標,以確保與項目有關的每一個人都能記住。項目成本的各個細節都應當清楚、明確、毫不含糊,并確保每個人對此都達成了一致的意見。
6、采用漸進的方式逐步實現目標
如果試圖同時完成所有的項目目標,只會造成重復勞動,既浪費時間又浪費錢。俗話說,一口吃不成個胖子。項目目標只能一點一點地去實現,并且每實現一個目標就進行一次評估,確保整個項目能得以控制。
7、項目應得到明確的許可,并由投資方簽字實施
在實現項目目標的過程中獲得明確的許可是非常重要的。應將投資方的簽字批準視為項目的一個出發點。道理很簡單:任何有權拒絕或有權修改項目目標的人都應當在項目啟動時審查和批準這些項目目標。
8、要想獲得項目成功必須對項目目標進行透徹的分析
研究表明,如果按照眾所周知記錄在案的業務需求來設計項目的目標,則該項目多半會成功。所以,項目經理應當堅持這樣一個原則,即在組織機構啟動項目之前,就應當為該項目在業務需求中找到充分的依據。
9、項目經理應當責權對等
項目經理應當對項目的結果負責,這一點并不過分。但與此相對應,項目經理也應被授予足夠的權利以承擔相應的責任。在某些時候,權利顯得特別重要,如獲取或協調資源,要求得到有關的中小企業的配合,做相應的對項目成功有價值的決策等等。
10、項目投資方和用戶應當主動介入,不能被動地坐享其成
多數項目投資方和用戶都能正確地要求和行使批準(全部或部分)項目目標的權力。但伴隨這個權力的是相應的責任——主動地介入項目的各個階段。例如,在項目早期要幫助確定項目目標;在項目進行中,要對完成的階段性目標進行評估,以確保項目能順利進行。項目投資方應幫助項目經理去訪問有關的中小企業和目標顧客的成員,并幫助項目經理獲得必要的文件資料。
11、項目的實施應當采用市場運作機制
在多數情況下,項目經理應將自己看成是賣主,以督促自己完成投資方和用戶交付的任務。項目計劃一旦批準項目經理應當定期提醒項目小組成員該項目必須滿足的業務需求是什么,以及該怎樣工作才能滿足這些業務需求。
12、項目經理應當獲得項目小組成員的最佳人選
最佳人選是指受過相應的技能培訓,有經驗,素質高。對于項目來說,獲得最佳人選往往能彌補時間、經費或其它方面的不足。項目經理應當為這些最佳的項目成員創造良好的工作環境,如幫助他們免受外部干擾,幫助他們獲得必要的工具和條件以發揮他們的才能。
在開始正文之前,我想先講兩個故事——關于軟件項目的故事。
故事一
有兩個軟件項目(姑且稱之為“項目 A”和“項目 B”),它們在開始時的預算都是 50 個人月,時間是 5 個月。
項目 A 在 5 個月后完工,耗費成本 50 人月
項目 B 在 6 個月后完工,耗費成本 70 人月
在軟件圈子里摸爬滾打多年的讀者們對這個故事一定有自己的判斷——而且我可以大致猜出是什么樣的判斷。不過先別著急,我們還有另一個故事。
故事二
有兩個軟件項目(仍然姑且稱之為“項目 A”和“項目 B”),它們在開始時的計劃都是交付 200 項功能。
項目 A 在項目結束時一次性交付了最初計劃的 200 項功能,但客戶發現其中大約 30 項功能沒有太大用處,而另外 30 項有用的功能要等到下一個項目才能實現。
項目 B 在第一個月結束時交付了第一個版本,此后每兩周交付一個新的版本。在項目進行的過程中,客戶進行了一次業務調整,加入了 90 項新的功能,并擱置了 50 項用處不大的功能。最終該項目交付了 240 項功能。
聰明的讀者大概注意到了,前后兩個故事講的是同一回事,同樣的兩個項目。現在我的問題來了:請問哪個項目是更成功的項目?
這個問題并不容易回答——實際上它沒有標準答案。站在很多軟件企業的立場上,項目 A 是一個理想的成功項目:按時間、按成本完成預先約定的任務。請注意,我用了“理想的”這個詞,稍后我還會解釋這個有趣的詞,因為實際上的軟件項目往往沒有那么理想。
而如果換一個角度,站在客戶的立場上呢?也許付錢購買軟件的客戶會有一些不同的想法。項目 B 從開始之后一個月便交付了第一個可工作的版本,從那時起客戶就開始使用這個軟件的部分功能,并且不斷地把自己使用的感受反饋給開發團隊。在真實的業務運營過程中,客戶甚至發現了一種新的盈利模式,并進行了一次大規模的業務調整,這次調整的結果也直觀地體現在軟件項目中。雖然項目B的整體交付速率低于項目 A,但它提供的所有功能都是客戶真正需要的,它們為客戶提供實實在在的價值——更不用說,客戶提前好幾個月就開始使用這個軟件。
實際上,這是一篇關于軟件價值的文章。和“成功項目”一樣,對于“軟件的價值”,不同的人也會有不同的定義。不過作為付錢購買軟件的客戶,他對于軟件價值的定義是一目了然的:他能夠從使用軟件中創造多少價值,軟件能夠為他的業務提供多少價值,這就是軟件的價值。或者說得更簡明一點:
軟件價值源自使用
這正是為什么很多客戶青睞“項目 B”的原因——我并不打算聲稱所有客戶都有同樣的觀點,稍后我也會舉出反例,但至少支持這一觀點的客戶不在少數。因為他們處在一個殘酷而快速變化的商業環境中:他們的供應商在變化,他們的客戶在變化,他們所處的經濟環境和政策環境也在變化。這一切的變化迫使他們的業務也要隨之變化。更要命的是,今天這個經濟全球化的時代是一個“快魚吃慢魚”的時代,客戶迫切希望新的軟件系統為他們帶來競爭優勢——哪怕這個軟件系統尚未完成,只要能夠投入使用。最后,客戶對于新的軟件系統究竟應該是什么樣子并沒有百分之百的把握,他們的想法往往要在真正使用軟件之后才會浮現成型。幾方面的因素加在一起,使得這些客戶更愿意盡快開始使用軟件、提出反饋、并不斷完善軟件,而不是提出一組需求、然后坐等幾個月之后原封不動地拿到這些功能。
一個真實的案例
在 ThoughtWorks 的一個項目中,開發者們在項目開始之后一個月內就發布了第一個版本——只有一些簡單的數據采集功能。在發布展示會上,發生了這樣的對話……
開發者:這是我們的第一個功能。我們從文本文件、Excel 數據表和遺留數據庫采集數據,現在我們的數據庫中有這些數據……(展示數據庫結構)
客戶:唔……有意思。要是你能做這樣一個查詢(寫出查詢要求),得到的結果可能會有用。
開發者:可是我們的界面上沒有地方做這樣的查詢操作。
客戶:啊,我不需要操作界面,只要每天深夜做一次查詢,把報表發到我的信箱就可以了。
開發者:這樣嗎……另一個問題是,這需要花我們幾天時間。
客戶:不要緊,把別的任務往后放幾天好了,我很想看到這份報表。
開發者:那好吧,下周我們就會開始提供這個報表。
猜猜結果怎么樣?一周之后客戶就開始每天接收這份報表,并根據報表內容做一些分析和決策。僅僅幾個月之后,這份報表給客戶帶來的收益就已經超過了整個項目的投資——這時項目其他部分的開發甚至還沒有完成。
想想這個客戶會怎么定義一個“成功的軟件項目”?好吧,也許這個項目超過了預期的時間,也許投入了更多的人力,但這些并不意味著“項目失敗”——只是付出更高的成本。關鍵在于,他投入的這些成本能夠帶來多大的收益,他的投資回報率是否劃算。對于這個客戶而言,如果項目能夠隨時給他提供可用的、能夠創造最大價值的軟件,能夠隨時讓——就像故事中提到的——這種有價值的想法得以實現,這就是一個成功的項目。
所以,親愛的讀者,請你忘記本文標題上出現的“敏捷”二字,我們在這里所說的不是別的,就是一種為客戶創造最大化價值的軟件開發方法。這樣的方法有很多種,但它們有一個共同的特點:盡快、盡可能頻繁地交付可以工作的軟件,讓客戶盡快開始使用軟件,從使用中創造價值、厘清思路、提出反饋。仍然以 ThoughtWorks 的項目為例,這些項目通常在啟動開發階段之后一個月內就會發布第一個版本,隨后每一周或每兩周發布一個新版本——每個版本都是一個可以工作的軟件,每個版本都比前一個版本具有更豐富的功能,并且每個版本都包含客戶認為迄今為止最有價值的那些功能。用軟件開發的“黑話”,“開發下一個版本”的過程叫做“迭代”,這些開發方法最大的共同點就是“迭代式開發”——不是一股腦地交付全部功能,而是每次增加一點、漸進地交付最有價值的功能。
軟件開發的夢想與真實
回到文章開始處的兩個故事。我曾經說過,對于很多軟件企業而言,項目 A 是一個“理想的”成功項目。那么,是什么讓情況變得不那么理想?
答案是一個所有軟件開發者耳熟能詳的詞:需求變更。在真實的項目中,客戶通常不會等到最后一天再照單全收整個項目,因為他知道自己的業務正在發生變化。這時需求變更就出現了,伴隨著來回的扯皮和討價還價。更糟的是,大量的需求變更發生在項目晚期——因為直到這時客戶才真正看到、使用到這個軟件,他的很多想法才真正浮現成型。隨著這種“最后一分鐘的需求變更”,項目超期、超出預算也就成了家常便飯。能夠像項目A這樣完工交付的,實在是鳳毛麟角的幸運兒。
為了對付需求變更這個噩夢,軟件開發者們還發明了另一個詞:變更控制。這個有趣的詞暗示著:需求變更是一種“不好”的東西,是需要“控制”的東西。然而站在客戶的角度上想想,他在親身使用了軟件之后提出的要求,難道不是最有價值的東西嗎?把這種真正創造業務價值的要求“控制”起來,難道是合理的嗎?
在前面我也暗示過,并非所有的客戶都一定青睞迭代式開發。那么,哪些軟件項目不一定需要迭代式開發呢?從整篇文章的內容不難看出,如果客戶的業務絕對不會變化,如果客戶的需求巨細靡遺非常明確,如果客戶不需要盡快開始使用軟件以便收回成本,那么迭代式開發對他的幫助就會小得多。不過,如果讀者認真思考的話,這樣的例子也許并不多——也許比你最初認為的要少得多。一個很好的例子是“神州六號”火箭使用的計算機控制系統。還有多少這樣的例子?讀者不妨試著自己想想。
如果我足夠幸運的話,也許一些讀者已經被這篇文章吊起了胃口:既然有這么好的軟件開發方法,既然它能夠為我們創造更大的價值,那還等什么呢,我們馬上就動手吧。事情不會那么簡單。為了讓迭代式開發能夠成為現實,為了確保盡快、盡可能頻繁地交付,為了確保每次交付的都是最有價值的功能,我們——包括軟件開發者、軟件企業和客戶——需要很多的改變。這里既有職責與權利的劃分,也有開發過程和團隊的重組,還有技術層面的實踐指導。這些正是敏捷方法學所涵蓋的內容。缺少了這些東西,“為客戶創造最大價值”就只能成為一句空話。在后續的文章里,我們將結合 ThoughtWorks 的實踐經驗,逐步介紹敏捷方法的方方面面。
最開始時微軟公司將Java當做一種能解決C和C++中存在的問題的語言,并不在意,并繼續維持和培訓著其C和C++技術和編程人員。接下來不幸的是,正當微軟盡力在Visual J++基礎上拓展Java功能,并使之與Windows操作系統緊密結合在一起的時候,Sun公司對微軟提出法律訴訟說其違反了許可證協議中的條款,最終的結果是微軟公司不得不停止其Visual J++產品的開發。(微軟公司仍然銷售Visual J++,但是從1998年10月以來就沒有新的版本發布,并且在.Net平臺上也沒有Visual J++的位置了)接下來的事情就很清楚了,微軟公司開發了C#語言。接下來的一部分將討論C#與Java的相似性。
C#與Java的區別
C#最引人的地方是它與Java的區別而不是其相似性。下面主要來介紹C#區別于Java的不同的運行特點及Java完全沒有的特點。
中間語言
當MSIL被編譯成最終的機器碼時,微軟公司在如何選擇上是非常靈活的。微軟公司很謹慎的對外宣稱說MSIL不是解釋型的,而是被編譯成機器碼。因為開發人員都有這樣一個觀念:Java程序天生就比C程序運行慢,所以這暗示著基于MSIL的程序優于解釋型的Java字節碼。當然,既然C#和其它MSIL產品編譯器還未發布,那么這一點就還未證明,但是Java無處不在的即時編譯器使得C#和Java在效能上是一樣的。象“C#是編譯型的,Java是解釋型的”這樣話只是銷售中的技巧。Java的字節碼和MSIL碼都是的類似匯編的中間語言,在運行時執行這些中間碼。
與COM的整合
對于基于Windows的C#開發人員來說,最大的收獲是對COM的無損整合,COM是微軟Win32的組件技術。實際上,任何一種.Net體系結構上的語言最終都可能去寫COM的客戶端和服務器端程序。用C#編寫的類也會作為COM組件的子類;結果類(resulting class)也能作為COM組件使用,并作為COM組件的子類。
微軟公司的目標是使越來越多的語言都能訪問組件,并使這些組件能整合到.Net體系結構中。已有幾個廠商開始著手開發支持.Net功能的編程語言,如COBOL和Haskell。開發人員能選擇不同的語言解決不同問題,更重要的是,開發人員不必為采用.Net體系結構而必須學習新語言,可以選擇一種他們熟悉的語言。
總結
本文的第一、二部分對C#做了一膚淺的總體介紹,主要是其產生動機及與Java的相似性。第三部分則涵概了C#的語言特點。用范例說明了C#與Java兩者在相似性外,它們又是非常不同的,有許多細微的語義和設計區別,適合不同的技術和市場環境,又談到了微軟公司對C#進行標準化方面的嘗試,及其對Java的影響。
c#與java的區別
1.屬性:
java中定義和訪問均要用get和set方法,可以不成對出現。
c#中是真正的屬性,定義時get和set必須同時出現,房問時用.號即可。不用get,set
2.對象索引
就是對象數組
public Story this [int index] {
3.C#中,不用任何范圍修飾符時,默認的是protect,因而不能在類外被訪問.
4.因為JAVA規定,在一個文件中只能有一個public類,而且這個類的名稱必須與文件名一模一樣,這是一個區別
5.在C#中,它是以Main方法來定位入口的.如果一個程序中沒有一個名為Main的方法,就會出"找不到入口的錯誤".不要把Main寫成main喲
6.C#預定義的簡單數據類型比Java多。例如,C#有unit,即無符號整數
7.忘掉Java中的static final修飾符。在C#中,常量可以用const關鍵詞聲明
C#的設計者還增加了readonly關鍵詞,readonly域只能通過初始化器或類的構造函數設置
8.公用類的入口點:c#是可以對Main進行重載(java中是main),允許有int返回值和空參數的Main
9.在Java中,switch語句只能處理整數。但C#中的switch語句不同,它還能夠處理字符變量。請考慮下面用switch語句處理字符串變量的C#代碼
10.C#沒有>>>移位操作符
11.goto關鍵詞:
Java不用goto關鍵詞。在C#中,goto允許你轉到指定的標簽。不過,C#以特別謹慎的態度對待goto,比如它不允許goto轉入到語句塊的內部。在Java中,你可以用帶標簽的語句加上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中,包的名字同時也是實際存在的實體,它決定了放置.java文件的目錄結構。在C#中,物理的包和邏輯的名稱之間是完全分離的
.NET中包的實體稱為程序集(Assembly)。每一個程序集包含一個manifest結構。manifest列舉程序集所包含的文件,控制哪些類型和資源被顯露到程序集之外,并把對這些類型和資源的引用映射到包含這些類型與資源的文件。程序集是自包含的,一個程序集可以放置到單一的文件之內,也可以分割成多個文件。.NET的這種封裝機制解決了DLL文件所面臨的問題,即臭名昭著的DLL Hell問題。
15.在Java中,java.lang包是默認的包,C#中不存在默認的包
16.C#中的訪問修飾符與Java中的基本對應,但多出了一個internal。簡而言之,C#有5種類型的可訪問性,如下所示:
public:成員可以從任何代碼訪問。
protected:成員只能從派生類訪問。
internal:成員只能從同一程序集的內部訪問。
protected internal:成員只能從同一程序集內的派生類訪問。
private:成員只能在當前類的內部訪問。
17.由于C#中不存在final關鍵詞,如果想要某個類不再被派生,你可以使用sealed關鍵詞
18.與Java不同,C#中的接口不能包含域(Field)。
另外還要注意,在C#中,接口內的所有方法默認都是公用方法。在Java中,方法聲明可以帶有public修飾符(即使這并非必要),但在C#中,顯式為接口的方法指定public修飾符是非法的。例如,下面的C#接口將產生一個編譯錯誤。
19.C#中的is操作符與Java中的instanceof操作符一樣,兩者都可以用來測試某個對象的實例是否屬于特定的類型。在Java中沒有與C#中的as操作符等價的操作符。as操作符與is操作符非常相似,但它更富有“進取心”:如果類型正確的話,as操作符會嘗試把被測試的對象引用轉換成目標類型;否則,它把變量引用設置成null。
20.C#仍舊保留了C++的內存手工管理方法,它適合在速度極端重要的場合使用,而在Java中這是不允許的
21.在C#中,所有的異常都從一個名為Exception的類派生
22.枚舉器即enum類型(java無),把它作為一個變量值的類型使用,從而把變量可能的取值范圍限制為枚舉器中出現的值。
23.結構(Struct)與類很相似,而結構是一種值類型,它存儲在棧中或者是嵌入式的,結構可以實現接口,可以象類一樣擁有成員,但結構不支持繼承
24.屬性聲明語法的第一部分與域聲明很相似,第二部分包括一個set過程和/或一個get過程
25.傳值方式:
在java中簡單數據類型的值傳參時,都以傳值方式;
在c#中如果加ref則會以引用的方式傳值(方法內部改變該參數,則外部變量一起跟著變);
加out與ref基本相同,但out不要求參數一定要初始化.
26.c#保留了指針。unsafe
27.代理:代理(delegate)可以看作C++或者其他語言中的函數指針
代理用來封裝可調用方法。你可以在類里面編寫方法并在該方法上創建代理,此后這個代理就可以被傳遞到第二個方法。這樣,第二個方法就可以調用第一個方法。
代理是從公共基類System.Delegate派生的引用類型。定義和使用代理包括三個步驟:聲明,創建實例,調用。代理用delegate聲明語法聲明。
|