2007年7月14日 星期六

Java 學習筆記 (1) - 入門篇

用來接收使用者輸入的新 class - Scanner

在 Java SE 5.0,在 package java.util 中提供了 Scanner class,用來取得使用者輸入的值,範圍為一個 word,而非僅僅是一個 byte;此外,在 package java.lang 中的 System class 中還提供了 C 語言中的 printf() 功能,以下用個範例簡單介紹:
import java.util.Scanner;

public class myScanner {
public static void main(String[] args) {
Scanner scn = new Scanner(System.in);
System.out.print("請輸入您的名字:");
System.out.printf("哈囉! %s\n", scn.next());
}
}
【註】關於各種不同資料型態的展示方式,可參考 package java.util 中的 Formatter class 中的說明。


接收包含空白的字串

在 Java 中要接收包含空白的字串,必須使用在 package java.io 中的 BufferedReader class,而為了擷取完整一行內容,一般都是使用 method readLine() 來處理,以下有一段範例程式:
import java.io.IOException;
import java.io.InputStreamReader;import java.io.BufferedReader;

public class myBufferReader {
public static void main(String[] args) throws IOException {
//要讀取包含空白的字串,則用 BufferedReader class
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("請輸入一列文字(可包括空白):");
String strInput = br.readLine();
System.out.println("您輸入的文字:" + strInput);
}
}


宣告不可改變的變數

在日常生活中,有某些數值是固定無須改變的,例如:圓周率。

而若要在程式中定義此種變數,必須使用「final」關鍵字,以下是範例語法:
final float myPI = 3.14;
而若是程式中有對此變數嘗試進行修改,compile 時就會出現錯誤。


位元運算

位元運算的部分可使用 bit operator(& 以及 |) 或是位元左移(<<)以及右移(>>),以下用一個範例來作簡單說明:
public class bitOperate {
public static void main(String[] args) {
//使用 logic operator 作 AND 運算
Integer intA = new Integer(10);
//與 1 進行 AND 運算,若為奇數,則為 TRUE
System.out.println(intA.toString() + " 是否為奇數:" + ((intA.intValue() & 1) != 0 ? "是" : "否"));

Integer intB = new Integer(1); // 0001
System.out.println("2 的 0 次方 = " + intB.toString());
intB = Integer.valueOf(intB <<= 1); // 0010
System.out.println("2 的 1 次方 = " + intB.toString());
intB = Integer.valueOf(intB <<= 1); // 0100
System.out.println("2 的 2 次方 = " + intB.toString());
intB = Integer.valueOf(intB <<= 1); // 1000
System.out.println("2 的 3 次方 = " + intB.toString());
}
}


變數宣告方式的不同

這個部分以整數為例,宣告整數有兩種方式,而使用起來卻有差異,以下用一個簡單的範例來說明:
public class AutoBox {
public static void main(String[] args) {
// 定義 Integer 物件
Integer intA = new Integer(100);
Integer intB = new Integer(100);

// 使用 logical operator 比較
if(intA == intB)
System.out.println("intA == intB");
else
System.out.println("intA != intB"); //兩個object參考名稱指向不同的object

//使用 equals() 作比較
if(intA.equals(intB))
System.out.println("intA == intB"); //兩個object中儲存的整數值相同
else
System.out.println("intA != intB");

//一般常用的宣告方式
int intC = 100;
int intD = 100;
if(intC == intD)
System.out.println("intC == intD"); //結果則合乎預期
else
System.out.println("intC != intD");
}
}


包含不同長度的一維陣列的的二維陣列

定義一個二維陣列,並指定不同長度的一維陣列在其中,以下用一個簡單範例來說明:
public class TwoDimArray {
public static void main(String[] args) {
//宣告一個 2-dimension array,長度不指定
int ary[][] = new int[2][];
//分別宣告兩個不同長度的 1-dimension array
ary[0] = new int[3];
ary[1] = new int[5];

for(int i = 0 ; i < ary.length ; i++) {
for(int j = 0 ; j < ary[i].length ; j++)
ary[i][j] = j + 1;
}

/*
* 結果如下:
* 1 2 3
* 1 2 3 4 5
*/

for(int i = 0 ; i < ary.length ; i++) {
for(int j = 0 ; j < ary[i].length ; j++)
System.out.print(ary[i][j] + " ");
System.out.println();
}
}
}


String Pool

JVM 為了讓字串處理工作更有效率,使用了 String Pool 的方式,讓同樣的字串可以重複使用,不需浪費無謂的記憶體空間,以下用一個範例來說明:
public class InternString {
public static void main(String[] args) {
//兩個為不同的 String object
String str1 = new String("flyweight");
String str2 = new String("flyweight");
System.out.println(str1 == str2); //false
System.out.println(str1.equals(str2)); //true

//JVM 會讓兩個 String object 指向 String pool 中的同一個字串
String str3 = "flyweight";
String str4 = "flyweight";
System.out.println(str3 == str4); //true

String strA = "fly";
String strB = "weight";
String strC = "flyweight";
String strD = null;
strD = strA + strB; //此時 String pool 中多了一個字串為 flyweight
System.out.println(strC == strD); //false
//intern() method 會去 String pool 中尋找是否有結合起來的字串
//若是有(此範例中為 strC),就會參考到該字串
System.out.println(strC == (strA + strB).intern()); //true
}
}


String Append

若在程式中有一堆 String Append 的部分,那這邊就要仔細看了!

使用一般的 String Append,會讓 String Pool 中不斷的產生新的 String Instance,不僅浪費資源,而且速度也很慢.....

因此 JDK 提供了 StringBuilder class,可以透過動態配置記憶體的方式,快速的進行 String Append 的工作,以下用一個範例程式來說明:
public class AppendStringTest {
//展示一般 string append 與 StringBuilder append 的速度差異
public static void main(String[] args) {
String strText = "";
long beginTime = System.currentTimeMillis();
for(int i = 0 ; i < 20000 ; i++)
strText += i;
long endTime = System.currentTimeMillis();
System.out.println(endTime - beginTime); //13219

StringBuilder sb = new StringBuilder("");
beginTime = System.currentTimeMillis();
for(int i = 0 ; i < 20000 ; i++)
sb.append(i);
endTime = System.currentTimeMillis();
System.out.println(endTime - beginTime); //10
}
}
從上面結果應該就可以很清楚看出兩種方法速度上的差異了吧!

Regular Expression

Regular Expression(正規表示式) 的強大,應該是很多人都知道的! 但是.....要寫出很精確又複雜的 regular expression,還真不是一件容易的事情,以下介紹使用在 java.util.regex package 中的 Pattern class 來產生 object 進行字串比對:
import java.util.regex.*;

public class RegExp {
public static void main(String[] args) {
String strPhones = new String("Justin的手機號碼:0939-100391\n" + "bush的手機號碼:0923-512345n" + "mormor的手機號碼:0939-666888");
//定義 regular expression
Pattern pt = Pattern.compile(".*0939-\\d{6}");
//字串比對
Matcher mt = pt.matcher(strPhones);
while(mt.find())
System.out.println(mt.group()); //印出符合 regular expression 的字串

//以下範例程式功能同上
String strText = new String("abcdebcadxbc");
Pattern ptn = Pattern.compile(".bc");
Matcher mth = ptn.matcher(strText);
while(mth.find())
System.out.print(mth.group() + " "); //abc ebc xbc
}
}

沒有留言:

張貼留言