參考鏈接: Java中的決策制定(if,if-else,switch,break,continue,jump)
第1章,計算機、程序和Java概述?
?
?包括【每個java初學者都應該搞懂的問題】
?http://blog.csdn.net/haobo920/article/details/5784990
?
?
1,java背景?
?
?特點:
?
?
?一次編譯,到處運行(Write Once, Run Anywhere.)。
?原理:
?
?
?Java源程序經編譯后生成.class字節碼文件,.class文件由Java虛擬機(JVM)解釋執行。不同的操作系統下,只要有相應的Java字節碼解釋程序,.class文件就能夠運行,這是Java跨平臺性的根本。
?
?
?比較:
?
?
?c和java編程與執行的過程如下圖所示:
?
?
?
??
?
分類:?
java application:應用程序是獨立的程序,能夠在任何有JVM的計算機上運行。?
java applet:? ?是一種特殊的Java程序,可以在web瀏覽器中直接運行。?
java servlet:? ?是一種特殊的Java程序,可以在web服務器上運行,創建動態的web內容。【Java Server Pages(JSP)則可以在服務器端生成動態網頁】??
2,創建、編譯和運行Java程序?
?
?示例:
?
?
public class Welcome{
? ? public static void main(String [] args){
? ? ? ? System.out.println("welcome");
? ? }
}?
創建:?
將該文件保存為Welcome.java:注意文件名必須與公用類名完全相同,這里是public class Welcome,所以文件名必須是Welcome.java?
編譯:?
再將文件Welcome.java編譯為Welcome.class:??
?
javac? Welcome.java?
?
運行:?
再執行字節碼文件Welcome.class:?
?
java? ?Welcome?
注意這里不再需要擴展名".class",JVM把命令的第一個參數當做文件名,如果寫作 java? Welcome.class則實際上會去查找Welcome.class.class。?
?
3,Java語法特點?
大小寫:?
Java是大小寫敏感的。?
注釋:? ? ??
除了//和/*這兩種注釋,Java還支持一種稱為Java文檔注釋的特殊注釋,以/**開頭,*/結尾,主要用于描述類、數據和方法,它可以通過JDK的javadoc命令轉換為HTML文件。?
?
/**Title: XXXX DRIVER 3.0
*Description: XXXX DRIVER 3.0
*Copyright: Copyright (c) 2003
*Company:XXX
*
* @author Java Development Group
* @version 3.0
*/?
命名習慣: 1、包名中的字母一律小寫。如:xxxyyyzzz。
?2、類名、接口名應使用名詞,每個單詞的首字母大寫。如:XxxYyyZzz。
?3、方法名,第一個單詞小寫,后面每個單詞的首字母大寫。如:xxxYyyZzz。
?4、變量名,第一個單詞小寫,后面每個單詞的首字母大寫。如:xxxYyyZzz。
?5、常量名中的每個字母一律大寫。如:XXX_YYY_ZZZ。?
?
JDK常用包: 1、java.lang——包含一些Java語言的核心類,如String、Math、Thread、System、Integer類等。
?2、java.awt——包含構成抽象窗口工具集的多個類,用來構建和管理應用程序的圖形用戶界面(GUI)。
?3、java.applet——包含applet運行所需的一些類。
?4、java.net——包含執行與網絡相關操作的類。
?5、java.io——包含能提供多種輸入/輸出功能的類。
?6、java.util——包含一些實用工具類。
?
Java關鍵字: 1、用于類和接口的聲明:class, extends, implements, interface
?2、包引入和包聲明:import, package
?3、數據類型:byte, boolean, char, double, int, long, float, short
?4、某些數據類型的可選值:flase, ture, null
?5、流程控制:break, case, continue, default, do, else, for, if, return, switch, while
?6、異常處理:catch, finally, throw, throws, try
?7、修飾符:abstract, final, native, private, protected, public, static, synchronilzed, transient, volatitle
?8、操作符:instanceof
?9、創建對象: new
?10、引用:this, supper
?11、方法返回類型:void
?12、保留字:const, goto
?
??
4,java語法之基本數據類型和基本操作?
?
?基本數據類型分類:
?
?
?字符類型char布爾類型boolean數值類型整數類型: byte short int long 浮點類型: float double?
??
?
?
?基本數據類型特點:
?
?
?Java
?不是純的面向對象的語言,不純的地方就是這些基本數據類型不是對象。當然初期Java的運行速度很慢,基本數據類型能在一定程度上改善性能。
?如果你想編寫純的面向對象的程序,用包裝器類是取代基本數據類型就可以了。
?
?
?Java中的基本數據類型不是對象,但有對應的包裝類。
?
?
?Java中的數組是對象。
?
?
?Java中的字符串是對象。
?
?
?Java中也內置實現了一些高級的數據結構,比如堆棧、集合、列表。
?
?
??
?
?
?1、基本類型的存儲空間固定:
?
?
?byte--8位,short--16位,int--32位,long--64位,float--32位,double--64位。這六種數字類型都是有符號的。
?固定的存儲空間正是Java可移植性、跨平臺的原因之一!
??
?2、Java不是純面向對象的:
?
?
?基本類型的存在導致了
?Java OOP的不純粹性。因為基本類型不是對象,一切皆對象是個小小的謊言。這是
?出于執行效率的權衡。
??
?3、整數類型范圍計算公式:
??
?使用公式(-2)^(位數-1)次冪到2^(位數-1)次冪-1確定整數類型(byte、short、int、long)的范圍。
?
?
?例如,byte范圍是:(-2)^7~(2)^7-1即-128~127
??
?4、布爾類型范圍:
?
?
?char是16位Unicode字符或者說是16位無符號整數,范圍從0到65535。即便如此,可以強制轉換非法的數據,如:char c1 = (char) 10000;? char c2 = (char) -200;。可以從二進制存儲的角度理解這點。
?
?
?
? 5、浮點類型的科學表示法:
??
?
? 在數學中e代表自然對數(Math.E給出了double值),而在Java中e代表10的冪次。浮點型的數可以這樣表示float f = 1e-27f; 代表1乘以10的負27次冪。
??
?6,浮點數的包裝類:
?
?
?BigInteger支持任意精度的整數。BigDecimal支持任意精度的定點數。
?
?
??
?
4.1 Java中的常量?
?
?1、整數常量表示方法:??
?
?
?
?十進制
?
?
?十六進制 ——以0x或0X開頭 八進制 ——以0開頭 長整形 ——以L(l)結尾
?
?
?2、浮點常量表示方法:
?
?
?
? ??
? 單精度浮點數——后面加f(F)
?
?
?雙精度浮點數——后面加d(D)? ?注: a.小數常量的默認類型是double型,所以float類型常量后一定要加f(F)。 b.浮點數常量可以用指數形式表示,如5.022e+23f?
?
?
?3、布爾常量表示方法:
?
?
?true或false
??
?4、字符常量表示方法:
?
?
?由英文字母、數字、轉義序列、特殊字符等的字符所表示,如'a'、'\t'等。
??
?Java中的字符占兩個字節,是用Unicode碼表示的,也可以使用'\u'加Unicode碼值來表示對應字符,如'\u0027'。
??
?常用的轉義字符有:
?
?
?\r——表示回車
??
?\n——表示換行
??
?\t——表示制表符,相當于Tab鍵
??
?\b——表示退格鍵,相當于Back Space鍵
??
?\'——表示單引號
??
?\”——表示雙引號
??
?\\——表示反斜杠“\”
?
?
?5、字符串常量表示方法:
?
?
?字符串常量用雙引號括起來。“A”是一個字符串,而‘A’是一個字符。
?
?
?6、null常量表示方法:
?
?
?null常量表示對象的引用為空。
?
?
?7、自定義常量:
?
?
?final double PI=3.14159;?
?4.2 Java中的變量:?
?
?
?注意:
?
?
?1、
?不要用字符$命名標示符,習慣上$只在機械地產生源碼時使用。
??
?4.3 Java算數運算符:?
?
?
?1、除法操作符(/):
?
?
?整數除法的結果是整數,
?小數部分被舍去。例如,5/2得2而不是2.5;-5/2得-2而不是-2.5。
?
?
?2、求余操作符(%):
?
?
?只有被除數是負數時,余數才是負的。例如,-7%3得-1。
?
3、短路操作符:?
&&邏輯與 也叫做短路與 因為只要當前項為假,它就不往后判斷了,直接認為表達式為假? ||邏輯或 也叫做短路或 因為只要當前項為真,它也不往后判斷了,直接認為表達式為真? ?
4.4 數據類型之間的轉換?
1、自動類型轉換(隱式類型轉換)條件:
?a.兩種類型彼此兼容
?b.目標類型的取值范圍要大于源類型
?
2、強制類型轉換(顯示類型轉換)格式:?
目標類型 常量 = (目標類型)值 注:
字符串可以使用加號“+”同其他的數據類型相連而形成一個新的字符串。
?
3、字符串與Int型之間的轉換:?
?
? ? ? ? //將整數值(2)轉換為字符串("2")
? ? ? ? String s = String.valueOf(2);
? ? ? ? String ss = Integer.toString(2);
? ? ? ? //將字符串("2")轉換為整數值(2)
? ? ? ? int i = Integer.parseInt(s); 字符串與double型之間轉換類似。?
?
4.5 控制臺輸入與對話框輸入?
1、控制臺輸入:?
?
? ? ? ? Scanner scanner = new Scanner(System.in);
? ? ? ? int intValue = scanner.nextInt();
? ? ? ? double doubleValue = scanner.nextDouble();
? ? ? ? String string = scanner.next();?
2、對話框輸入:??
?
import javax.swing.JOptionPane;
public class TestScanner {
? ? public static void main(String[] args) {
? ? ? ? String x="Welcome to Java!";
? ? ? ? String y="Display the message!";
? ? ? ? /*
? ? ? ? ?*消息框輸入
? ? ? ? ?*/
? ? ? ? //其中x是用于提示信息的字符串,y是用于對話框標題的字符串。
? ? ? ? String string = JOptionPane.showInputDialog(null,x,y,JOptionPane.QUESTION_MESSAGE);
? ? ? ? //其中x是用于提示信息的字符串。
? ? ? ? String string2= JOptionPane.showInputDialog(x);
? ??????
? ? ? ? /*
? ? ? ? ?*消息框輸出
? ? ? ? ?*/
? ? ? ? ?//其中x是所要顯示的字符串,y是對話框的標題和字符串。
? ? ? ? ?JOptionPane.showMessageDialog(null,x,y,JOptionPane.INFORMATION_MESSAGE);
? ? ? ? ?//其中x是所要顯示的字符串。
? ? ? ? ?JOptionPane.showMessageDialog(null,x);? ? ?
? ? }
}
??
?
?
4.6 產生隨機數0~9?
?
(int)(Math.random()*10)?
?
4.7 Java的格式化輸出?
舉例:?
?
int count = 5;
double amount = 45.65;
String s=String.format("count is %d and amount is %f",count,amount);??
System.out.println(s);?
?
常用的格式描述符:?
?
?
描述符輸出舉例%b布爾值true或false%c字符‘a’%d十進制整數200%f浮點數45.6400000%e標準科學計數法形式的數4.556000e+01%s? 字符串“Java is cool”?
?
指定寬度和精度:
?
?
舉例輸出%5c輸出字符并在它前面加4個空格%6b輸出布爾值,在false前面加一個空格,在true前面加兩個空格%5d輸出整數項,寬度至少為5。 如果項目數字的位數少于5個,前面加空格,如果項目的位數多于5個,寬度自動增加。%10.2f輸出寬度至少為10的浮點數,包括小數點和小數點后面兩位。 這樣,小數點前有7位,數字前面加空格。如果小數點前的位數大于7,寬度自動增加。%10.2e輸出寬度至少為10的浮點數,包括小數點和小數點后面兩位和指數部分。 如果按科學計數法顯示的數字小于10,前面加空格。%12s輸出寬度至少為12的字符串。 如果字符串少于12個字符,前面加空格。如果字符串項目多于12個字符,寬度自動增加。?
?
?
?在string中格式化:
?
?
?String s=String.format("count is %d and amount is %f",5,45.22);?
?
?
??
?
5,Java語法之程序控制流程?
5.1、if條件語句?
a.if...?
?
?
if(test)
{
? ? ...
}?
b.if...else...?
?
?
if(test)
{
? ? ...
}
else
{
? ? ...
} 可簡寫為:變量 = 布爾表達式? 語句1:語句2;
?
c.if...else if...else...?
?
?
if(test1)
{
? ? ...
}
else if(test2)
{
? ? ...
}
else
{
? ? ...
}?
?
?
5.2、switch選擇語句?
switch(表達式)
{
case 取值1:
? ? 語句塊1;
? ? break;
...
case 取值n:
? ? 語句塊n;
? ? break;
default:
? ? 語句塊n+1;
? ? break;
} 語句從匹配處開始執行,
直到遇到break語句或是達到switch語句的末端。這種情形稱作向下貫通行為。
?
?
5.3、條件表達式?
?
y=(x>0)?1:-1;?
5.4、while循環語句?
while(條件表達式)
{
? ? 執行語句
}?
5.5、do while循環語句?
do{
? ? 執行語句
}while(條件表達式);?
5.6、for循環語句?
for(int i = 0; i<10;i++)
{
? ? 執行語句
}?
5.7、增強for循環?
for (循環變量類型 循環變量名稱: 要被遍歷的對象)
{
? ? 執行語句
}?
5.8、break與continue語句 a.無標號的break語句會跳出最內層循環(while,do,for,switch),執行下一條語句。
?
b.無標號的continue語句的作用是跳過當前循環的剩余語句塊,接著執行下一次循環。?
c.帶標號的break或continue可以跳轉到指定的循環層次語句位置。?
?
? ? outer:
? ? ? ? for(int i = 1; i<10; i++)
? ? ? ? {
? ? ? ? inner:
? ? ? ? ? ? for(int j = 1; j<10; j++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(i*j>50)
? ? ? ? ? ? ? ? ? ? break outer;
? ? ? ? ? ? ? ? ? ? //continue outer;
? ? ? ? ? ? ? ? System.out.println(i*j);
? ? ? ? ? ? }
? ? ? ? }?
?
??
?6,Java語法之函數?
6.1、Java中函數的格式:?
?
?1、定義函數的格式
? 返回值類型 函數名(參數類型 形式參數1,參數類型形式參數2,...)
? {
? ? ? 程序代碼
? ? ? return 返回值;
? }
??
?2、函數的重載
? 函數的重載就是在一個類中可以同時存在一個以上的同名函數,只要它們的參數個數或類型不同即可。
??
?
6.2、Java中函數的參數都是傳值的?
?
?眾所周知,java和C、C++中都不能通過值傳遞的方式實現兩個整數的交換。
??
?
?
?即下面的函數是不能成功交換兩個整數的:
?
?
?public void swap1(int a,int b)
{?
? ? //值參數傳遞不能實現交換兩個整數
? ? ? int t;
? ? ? t = a;
? ? ? a = b;
? ? ? b = t;
}?
??
?
?
?在C++,可以通過引用或者指針來實現兩個整數的交換,實質上是通過地址傳遞來實現兩個整數的交換的。
??
?
?
?//c++代碼
void swap2(int &a,int &b)//引用傳遞?
{
?int temp;
?temp = a;
?a = b;
?b = temp;
}
?還可以通過指針來實現兩個整數的交換
??
?//C++代碼
void swap2(int *a,int *b)//指針,地址傳遞?
{
?int temp;
?temp = *a;
?*a = *b;
?* b = temp;
}?
??
?那么java中又是如何實現兩個整數的交換呢?
??
?
?
?方法1:通過數組方式交換(實際Java中數組也是對象,所以引用傳遞):
?
?
?這是因為java中數組的傳遞是引用傳遞,如果一定要通過一個? ?method? ?來實現,下面的形式也許可以:
??
?
?
?void? swap(int[]? a)? ?//傳入數組,相當于引用傳遞
{?
? ? if(a==null||a.length!=2)
? ? ? ? throw new IllegalArgumentException();
? ??????
? ? int temp=a[0];
? ? a[0]=a[1];
? ? a[1]=temp;
}??
? 方法2:構造對象
?
?
?這也是因為對象是以引用傳遞方式:
?
?
?class Num
{
? ? int value;
}
?
?
public class TestSwap?
{
? ? public static void main(String args[])
? ? {
? ? ? ? Num a=new Num();
? ? ? ? Num b=new Num();
? ? ? ? a.value=12;
? ? ? ? b.value=234;
? ? ? ? System.out.println("a="+a.value+" b="+b.value);
? ? ? ? swap(a,b);
? ? ? ? System.out.println("a="+a.value+" b="+b.value);
? ? }
? ? public static void swap(Num a,Num b)
? ? {
? ? ? ? Num temp=new Num();
? ? ? ? temp.value=a.value;
? ? ? ? a.value=b.value;
? ? ? ? b.value=temp.value;
? ? }
}
?
??
??
?
?
?而Integer不行,?
?
?
?1、Integer本身是值對象(value? ?object),不能修改它的內容(初始化后不能改變其值)。實際上,串對象String都不能改變;?
? 2、就算Integer本身可以修改,自動裝箱、拆箱也不靈:?
?
?
?void swap(Integer a,Integer b)? ?
{? ?交換ao和bo中的實際數據? ?}?
int? ?a,b;?
swap(a,b);? ?//? ?自動裝箱機制生成了兩個臨時對象,不過調用返回時不能傳回a和b。?
最多只能這樣:?
Integer? ?a1=a;?
Integer? ?b1=b;?
swap(a1,b1);?
a? ?=? ?a1;?
b? ?=? ?b1;?
??
?
7,Java語法之數組?
7.1、數組的定義?
?
?數組是對象。
?如:
?
int [ ]? x = new int[100];
?或 :int x [ ]? = new int[100];(這種方式主要是為了適應C/C++程序員)?
聲明一個數組變量:int [ ] x;并不會在內存中給數組分配任何空間,僅創建一個引用數組的存儲地址。??
數組創建后,其元素賦予默認值,數值型基本數據類型默認值為0,char類型為‘\u0000’,boolean類型為false。?
7.2、數組的靜態初始化 如:int [ ] x = new int [ ] {3,4,5};
?
7.3、多維數據 如:
?int [ ][ ] xx = new int [3][ ];
?xx[0] = new int[3];
?xx[1] = new int[2];
?xx[2] = new int[3];?
?
7.4、數組的復制?
錯誤:array1 = array2; 該語句并不能將array2的內容復制給array1,而是將array2的引用傳給了array1。使用array1 = array2 這個語句之后,array1,array2指向了同一個數組,如下圖所示:??
??
這樣,array2之前所引用的數組不能再引用了,變成了垃圾,會被JVM自動回收的。所以使用“=”是不能進行數組的復制,它實際上是將=右邊的數組的引用傳給了=左邊的數組變量,達到兩個數組變量指向同樣的內存地址。??
常用的數組復制的方法有以下3種: 1.使用循環語句逐個復制數組的元素(最簡單的方法)??
2.使用System類中的靜態方法arraycopy??
?
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length) 參數:
?src?
- 源數組。
?srcPos?
- 源數組中的起始位置。
?dest?
- 目標數組。
?destPos?
- 目標數據中的起始位置。
?length?
- 要復制的數組元素的數量。
?另外:arraycopy方法沒有給目標數組分配內存空間,復制前需要創建目標數組并給它分配內存。復制完成后,各自占有獨立空間。?
?
?
?//使用System中的靜態方法arraycopy復制數組? ?
int[] targetArray = new int[sourceArray.length];
System.arraycopy(sourceArray, 0, targetArray, 0, sourceArray.length);??
3.使用clone方法復制數組??
?
int[] targetArray = new int[sourceArray.length];
/*使用clone方法將int[]型數組,將sourceArray復制到targetArray
*由于clone方法返回值的類型是對象Object,所以要使用(int[])強制轉換為int[]
*/?
targetArray = (int[])sourceArray.clone();?
7.5、數組作為形參?
對于基本數據類型的參數,傳遞的是實參的值。?
對于數組類型的參數,傳遞的是數組的引用。?
7.6、Arrays類?
進行排序:?
?
java.util.Arrays.sort(array);?
?二分查找:?
?
?
java.util.Arrays.binarySearch(array,key);?
?數組相當判斷:?
?
?
java.util.Arrays.equals(array1,array2);?
?
8,面向對象的概念?
8.1、面向對象舉例?
?
//TestCircle.java
class Circle
{
? ? //---------------靜態數據-----------------
? ? static int numOfObjects=0;? ?//靜態數據
? ??
? ? //---------------靜態方法-----------------
? ? static int getNumOfObjects() //靜態方法,其中只能使用靜態數據,不能用實例變量radius
? ? {
? ? ? ? return numOfObjects;
? ? }
? ??
? ? //---------------數據域-----------------
? ? double radius=1.0;
?
? ??
? ? //---------------構造方法1-----------------
? ? //類如果沒有聲明構造方法,類隱含聲明一個方法體為空的無參構造方法,此稱之為默認構造函數
? ? Circle()
? ? {
? ? ? ? numOfObjects++;
? ? }
?
? ? ? ??
? ? //---------------構造方法2-----------------
? ? //1,構造方法可以重載
? ? //2,構造方法無返回值,與類同名
? ? //3,構造方法的調用是在創建一個對象使用new操作符時進行的
? ? //4,構造方法的作用是初始化對象
? ? Circle(double radius)
? ? {
? ? ? ? this.radius=radius;
? ? ? ? numOfObjects++;
? ? }
?
?
? ? double getArea()
? ? {
? ? ? ? return radius*radius*Math.PI;
? ? }
}
?
//文件中唯一的公共類:包含main方法,與文件名同名,public。
public class Main
{
? ? public static void main(String args[])
? ? {
? ? ? ? Circle myCircle = new Circle(10);
? ? ? ? System.out.println(myCircle.getArea());
? ? }
}?
注意:?
?
1,可以把多個類放在一個文件中,但一個文件只能有一個公共類,且該公共類與文件名同名,包含main方法,如這里的TestCircle類。?
2,類的數據域如果沒有顯式賦值,會有默認值:引用型(如String)會賦值null,數值型(如int)會賦值0,boolean型會賦值false,char型會賦值'\u0000';?
? ? ? 而Java中方法的局部變量則不會有默認值,這時會報錯。 3,如果認為對象不再需要,可以顯示賦值null,這樣Java虛擬機將自動回收其所占空間。??
8.2 、靜態變量、靜態方法和常量?
1,靜態變量、靜態方法都是屬于類而不是屬于對象。?
2,靜態方法只能調用靜態變量、靜態方法,不能調用實例變量和實例方法;反之,實例方法卻可以調用實例變量、實例方法、靜態變量、靜態方法。這是因為實例變量是各個對象所獨有的,直接調用就不知道是哪個對象了。?
3,常量的定義是:final double PI=3.14;它僅僅表示的是不可重新賦值。靜態常量則可以被大家直接公用:static final double PI=3.14;?
8.3、可見性修飾符(訪問控制)?
1,訪問修飾符是指private,默認修飾符(不用修飾符),protected,public四種。這里按照了訪問修飾符所規定的被訪問范圍從小到大的順序排列。?
2,訪問修飾符是用來控制被訪問范圍的。用不同的訪問修飾符修飾一個對象是為了使該對象獲得不同的被訪問范圍。訪問修飾符所修飾的對象:可以是類的數據成員、類的方法成員或類本身和接口。訪問的方式其實也分為三種:在類內直接訪問數據成員和調用方法成員,在類外通過類來訪問static成員或實例對象來訪問非static成員,和以繼承的方式訪問(這里,“以繼承的方式訪問”如果深究下去,還可以包括直接訪問基類的數據成員和方法成員與對基類的方法成員進行覆蓋以達到“多態”效果等方式)。因此,如果用簡單的乘法原理來說,可供陳述的情況就有4*3*3=36種之多。?
3,可見性修飾符用于類類的數據成員、類的方法成員或類本身和接口。但不能用于方法中的局部變量,否則引起編譯錯誤。?
4,舉個特別的例子:?
大多數情況下,構造方法應該是公用的。但是,如果想防止用戶創建類的實例,可以使用私有的構造方法。比如,因為Math類的所有方法都是靜態的,沒有必要創建實例。一個解決辦法就是在類中定義一個虛設的私有的構造方法,Math類中有一個如下所示的私有構造方法,所以,Math類不能實例化:?
?
private Math(){
}?
?5,類本身只有兩種訪問控制:public和默認(定義時無訪問控制符)。
?
1、public修飾的類能被所有的類訪問。
?
2、默認修飾的類只能被同一包中所有的類訪問。
?
?
8.4、Java的可變類和不可變類?
?
1, 可變類? :當你獲得這個類的一個實例引用時,你可以改變這個實例的內容。 不可變類:當你獲得這個類的一個實例引用時,你不可以改變這個實例的內容。不可變類的實例一但創建,其內在成員變量的值就不能被修改。??
2,如何創建一個自己的不可變類(Mutable and Immutable Objects):?
.所有成員都是private .不提供對成員的改變方法,例如:setXXXX .確保所有的方法不會被重載。手段有兩種:使用final Class(強不可變類),或者將所有類方法加上final(弱不可變類)。 .如果某一個類成員不是基本類型(primitive)或者不可變類,必須通過在成員初始化(in)或者get方法(out)時通過深度clone方法,來確保類的不可變。??
3,一個類的所有數據都是私有的,且沒有修改器,但它不一定是不可變類。這突出反映在2中的第四點,可以有以下一個例子:?
?
public class Student
{
? ? private int id;
? ? private BirthDate birthDate;
?
?
? ? public Student(int id, BirthDate birthDate)
? ? {
? ? ? ? this.id = id;
? ? ? ? this.birthDate = birthDate;
? ? ? ? //深度復制:this.birthDate = new BirthDate(birthDate);
? ? }
?
?
? ? //Getters
? ? public int getId()
? ? {
? ? ? ? return id;
? ? }
? ? public? BirthDate getBirthDate()
? ? {
? ? ? ? return? birthDate;
? ? ? ? //深度復制:return new BirthDate(birthDate);
? ? }
}
?
?
public? class? BirthDate
{
? ? private int year;
? ? private int month;
? ? private int day;
?
?
? ? public BirthDate(int year, int month, int day)
? ? {
? ? ? ? this.year = year;
? ? ? ? this.month = month;
? ? ? ? this.day = day;
? ? }
?
?
? ? //Setters
? ? public void setYear(int year)
? ? {
? ? ? ? this.year = year;
? ? }
}?
?
其中,Student類所有數據均私有,且沒有Setters,但是使用getBirthDate()方法返回數據域birthDate,這是BirthDate對象的一個引用,而BirthDate有Setters,通過這個引用,可以用setYear()方法改變year,因此也就改變了Student對象的內容,因此,也就沒有達到不可變對象的效果。?
?
要使一個類成為不可變類,必須將所有的數據域說明為私有的,并且不含返回引用“非不可變對象數據域的修改器和訪問器”。?
解決方法是:深度復制(具體見上代碼注釋部分)?
??
8.5、關鍵字this?
?
class Foo
{
? ? int i = 5;
? ? static double k = 0;
? ??
? ? void setI(int i)
? ? {
? ? ? ? this.i = i;
? ? }
? ??
? ? static void setK(int k)
? ? {
? ? ? ? Foo.k = k;
? ? }
}?
【注意】隱藏的實例變量用this來引用,隱藏的靜態變量用類名來引用。?
另外,可以使用"this(參數)"形式調用其它構造函數。?
8.6、垃圾回收: a.finalize()方法。finalize()方法的作用類似于C++中的析構方法,其是在對象已變成垃圾即將從內存中釋放前調用(不是在對象變成垃圾前調用)。這并不是一個可靠的機制。
?b.System.gc()。這個方法可以強制啟動垃圾回收器來回收垃圾。
??
?
9,String類?
9.1、String類概述?
?
?1、String是final類,不可繼承;
? 2、String類比較字符串相等時時不能用“ == ”,只能用“equals”;?
? 3、String類不可更改,StringBuilder和StringBuffer類能夠創建靈活可變的字符串。
??
?
9.2、String的字符串常量池?
?
?String s1="abc";
String s2="abc";
System.out.println(s1==s2);//true?
?
? ?
??
??
? String s1="abc";
String s2=new String("abc")
System.out.println(s1==s2);//false?
? ?
??
??
? String s1="abc";
String s2=s1.intern();
System.out.println(s1==s2);//true?
? ?
? 1,Java有一個初始時為空的
?字符串池,它由類 String 私有地維護。
?
?
?2,
?字符串對象的創建方式有兩種,如下:
?
?
?String s1 = new String("");? ?//第一種
? String s2 = "";? ? ? ? ? ? ?
? ? //第二種
??
?第一種始終不會入池的. 第二種要看情況而定(等號右邊如果是常量則入池,非常量則不入池)
? 例:
? String s3 = "a" + "b"; //"a"是常量,"b"是常量,常量+常量=常量,所以會入池.
? String s4 = s1 + "b";? ?//s1是變量,"b"是常量,變量+常量!=常量,所以不會入池.
??
?一旦入池的話,就會先查找池中有無此對象.如果有此對象,則讓對象引用指向此對象;如果無此對象,則先創建此對象,再讓對象引用指向此對象.
??
?
?
?現在考慮上述代碼,為了節省Java虛擬機的效率和內存,在
?以String s1=“abc”的方式建立String引用聲明時,會首先去Java的字符串池中查找是否有這個對象,如果有了,則直接指向它。所以這里建立s1時,字符串池為空,所以在字符串池中建立對象“abc”,并將s1指向它,后又建立s2,會先去字符串池中查找,有了,所以也指向它,這樣,s1與s2指向的其實是同一個對象。
?
?
?而用String s2=new String("abc")方法聲明的,都不會去常量池,這時s2單獨會生成一個對象,二者指向不同。
?
?
?java字符串String的實例方法intern()【也叫字符串扣留】就是為解決這個問題而來的,但使用了intern()字符串扣留方法后能使用“==”操作符比較字符串的結果只是該方法的衍生品,它的主要目的是為了減少java程序中對同一字符串對象的重復引用(reference)從而減少內存的使用提升效能,因為使用字符串扣留intern()實例方法就能夠確保不存在封裝有完全相同字符串的兩個String對象,因此所有的String對象封裝的字符串對象都唯一。
?
?
?當調用
? intern 方法時,如果池已經包含一個
?等于此 String 對象的字符串(該對象由 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,并且返回此 String 對象的引用。?
??
??
?
9.3、字符串轉換?
?
?注:
?字符串可以使用加號“+”同其他的數據類型相連而形成一個新的字符串。
??
?字符串與Int型之間的轉換:?
??
? ? ? ? ?//將整數值(2)轉換為字符串("2")
? ? ? ? String s = String.valueOf(2);
? ? ? ? String ss = Integer.toString(2);
? ? ? ? //將字符串("2")轉換為整數值(2)
? ? ? ? int i = Integer.parseInt(s); 字符串與double型之間轉換類似。
??
??
?
10,基本數據類型的包裝類?
Java為每一種基本數據類型提供類一個包裝類:?
?
基本類型包裝類charCharacterboolean BooleanbyteByteshortShortintIntlongLongfloatFloatdouble Double?
?
?
11,文本I/O?
示例代碼如下,編寫名為ReplaceText類,用新的文本字符串代替舊的文本字符串,使用方法:java ReplaceText sourceFile targetFile oldString newString?
主要使用Scanner來讀數據,用PrintWriter來寫數據:?
?
import java.io.*;
import java.util.*;
?
public class ReplaceText {
? ? public static void main(String[] args) throws Exception {
? ? ? ? // Check command line parameter usage
? ? ? ? if (args.length != 4) {
? ? ? ? ? ? System.out.println("Usage: java ReplaceText sourceFile targetFile oldStr newStr");
? ? ? ? ? ? System.exit(0);
? ? ? ? }
?
? ? ? ? // Check if source file exists
? ? ? ? File sourceFile = new File(args[0]);
? ? ? ? if (!sourceFile.exists()) {
? ? ? ? ? ? System.out.println("Source file " + args[0] + " does not exist");
? ? ? ? ? ? System.exit(0);
? ? ? ? }
?
? ? ? ? // Check if target file exists
? ? ? ? File targetFile = new File(args[1]);
? ? ? ? if (targetFile.exists()) {
? ? ? ? ? ? System.out.println("Target file " + args[1] + " already exists");
? ? ? ? ? ? System.exit(0);
? ? ? ? }
?
? ? ? ? // Create input and output files
? ? ? ? Scanner input = new Scanner(sourceFile);
? ? ? ? PrintWriter output = new PrintWriter(targetFile);
?
? ? ? ? while (input.hasNext()) {
? ? ? ? ? ? String s1 = input.nextLine();
? ? ? ? ? ? String s2 = s1.replaceAll(args[2], args[3]);
? ? ? ? ? ? output.println(s2);
? ? ? ? }
?
? ? ? ? input.close();
? ? ? ? output.close();
? ? }
}
?
?
?
?
12,類的繼承和多態?
?
12.1、Java中繼承的特點 1、使用extends關鍵字表示繼承,通過繼承可以簡化類的定義。
?2、Java只支持單繼承,可以有多重繼承。
?3、
子類繼承父類所有的成員變量和成員方法,但不繼承父類的構造方法。在子類的構造方法中可以顯示用super( args )調用父類的構造方法,如果子類的構造方法中沒有顯示的調用父類的構造方法,也沒有使用this關鍵字調用重載的其他構造方法,則在產生子類的實例對象時,系統默認調用父類無參數的構造方法,相當于系統默認調用了一次super()。
?【注】:一個類中如果定義了有參構造方法而沒有重寫無參構造方法,無參構造方法將失效。所以我們在定義類時,只要定義了有參構造方法,通常還要定義一個無參構造方法。
?4、子類覆蓋父類的方法時,覆蓋方法必須和被覆蓋方法具有相同的方法名稱、參數列表和返回值類型,且子類不能使用比父類中被覆蓋方法更嚴格的訪問權限。
?
//基類Fruit
public class Fruit
{
? ? String id;? ? ? ?//1
? ? void show(){};? ?//2
}
//擴展類Apple
public class Apple extends Fruit
{
? ? String id;? ? ? ?//3
? ? void show(){};? ?//4
}
Apple apple = new Apple();//定義apple,類型:擴展類Apple;實例:擴展類Apple
Fruit fruit = apple;? ? ? //定義fruit,類型:基類fruit;? 實例:擴展類Apple。
?
fruit.id;? ? ?//1
apple.id? ? ? //3
fruit.show(); //4
apple.show(); //4 這說明:?
?
父子同名,屬性的調用:看實際類型。因為這是靜態匹配的,在編譯時就做好了。?
父子同名,方法的調用:看聲明類型。因為這是動態綁定的(多態性),需要看實際對象。?
12.2、Java中的對象轉換和instanceof?
建議把變量聲明為父類類型,這樣可以接收任何子類類型的值。?
?
Object object1 = new Circle();
Object object2 = new Rectangle();
display(object1);
display(object2);
? ??
public static void display(Object object)
{
? ? if(object instanceof Circle)
? ? {
? ? ? ? ((Circle)object).display();
? ? }
? ? else if (object instanceof Rectangle)
? ? {
? ? ? ? ((Rectangle)object).display();
? ? }
} 再比如,覆蓋Circle中的equals方法:?
?
?
? public boolean equals(Object o)
? ? {
? ? ? ? if(o instanceof Circle)
? ? ? ? {
? ? ? ? ? ? return radius == ((Circle)o).radius;
? ? ? ? }
? ? ? ? return? false;
? ? }?
?
13,Object類 Java中所有類(包括用戶自己定義的類)都自動繼承Object類,即Object類是所有類的父類。
?
13.1,Object中常用方法?
?
?public boolean equals(Object obj)比較當前對象與obj是否為同一對象,返回值:ture/false 由于Object中如下示: public boolean equals(Object obj){?
? return (this == obj);
} 所以Object的子類需要覆蓋該方法。public String toString()返回當前對象的字符串表達形式: public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
} public native int hashCode()返回對象的Hash碼,Hash碼是標志對象的唯一值。 約定:若兩個對象equals若返回的是true,則對象的散列碼必須一致。 所以需要適當修改。 【注】native表示實現方法的程序設計語言不是Java。protected void finalize()throws Throwable對象銷毀時被調用。 這是Java虛擬機調用的,在自己的程序中不用書寫任何調用該方法的代碼。protected native Object clone() throws CloneNotSupportedException;創建并返回此對象的一個副本. 所有要進行"克隆"的對象所屬的類必須實現java.lang.Cloneable接口.public final native Class<?> getClass();;返回此時的Java的運行時類,這是Java反射機制的一個應用。 一個類在使用時必須先裝入。 Java虛擬機在裝入類時,創建一個包含類信息的對象。 這個對象時Java.lang.Class的一個實例,它描述有關類的信息。?
?
Reflection是Java 程序開發語言的特征之一,它允許運行中的 Java 程序對自身進行檢查,或者說"自審",并能直接操作程序的內部屬性。例如,使用它能獲得 Java 類中各成員的名稱并顯示出來。 Java 的這一能力在實際應用中也許用得不是很多,但是在其它的程序設計語言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒有辦法在程序中獲得函數定義相關的信息。
?
這里只簡略減少Class類。?
??
??
?
?
?
??
21,抽象類與接口?
抽象類 1、抽象類——包含抽象方法的類就叫做抽象類。一個抽象類中可以有一個或多個抽象方法。 2、抽象方法的寫法:abstract 返回值類型 抽象方法名 (參數列表) 3、抽象方法用abstract關鍵字修飾,只需要聲明不需要實現。帶有抽象方法的類必須也用abstract聲明為抽象類。 4、抽象類不能被實例化,其子類必須覆蓋所有的抽象方法后才能被實例化,否則其子類也還是抽象類。? ?接口 1、接口是一種特殊的抽象類,其中只包含常量和方法的定義,而沒有變量和方法的實現。 2、接口中定義的變量是全局靜態常量,默認是用public static final標記的。 3、接口可以繼承接口。如果一個類只實現了接口中定義的部分方法,那么這個類是抽象類。 4、一個類可以在繼承一個父類的同時實現一個或多個接口,此時extends關鍵字必須位于implements關鍵字之前。 5、設計接口的目的是為了讓類不必受限于單一繼承的關系,而可以靈活的同時繼承一些共有的特性,從而達到多重繼承的目的。? ?對象的多態性 1、子類能夠自動轉換為父類類型。如:Bird b = new Bird();? Animal a = b; 2、父類轉換為子類需要進行強制類型轉換,強制類型轉換的前提是需要提前知道要轉換的父類引用類型對象的本來面目確實是子類類型的。 3、可以使用instanceof操作符判斷一個類是否實現了某個接口,或用來判斷一個實例對象是否屬于某個類。其語法格式為:對象? ? instanceof 類(或接口) 4、Object類是Java類層中的最高層類,是所有類的超類。自定義類中必須覆蓋Object類的equals方法,否則調用的是Object類的equals方法。??
??
22,異常處理?
軟件開發中一個古老的說法是:80%的工作使用20%的時間。80%是指檢查和處理錯誤所付出的努力。在許多語言中,編寫檢查和處理錯誤的程序代碼很乏味,并使應用程序代碼變得冗長。原因之一就是它們的錯誤處理方式不是語言的一部分。盡管如此,錯誤檢測和處理仍然是任何健壯應用程序最重要的組成部分。? Java提供了一種很好的機制,用強制規定的形式來消除錯誤處理過程中隨心所欲的因素:異常處理。它的優秀之處在于不用編寫特殊代碼檢測返回值就能很容易地檢測錯誤。而且它讓我們把異常處理代碼明確地與異常產生代碼分開,代碼變得更有條理。異常處理也是Java中唯一正式的錯誤報告機制。? ? 第一部分? ? 異常? ?1、拋出異常。所有的標準異常類都有兩個構造器:一個是缺省構造器,一個是帶參數的構造器,以便把相關信息放入異常對象中。? ? ? throw new NullPointerException();? ? ? throw new NullPointerException("t = null");? 2、如果有一個或者多個catch塊,則它們必須緊跟在try塊之后,而且這些catch塊必須互相緊跟著,不能有其他任何代碼。C++沒有這樣的限制,所以C++的異常處理處理不好就會寫得很亂,拋來拋去的。? 3、使用try塊把可能出現異常的代碼包含在其中,這么做的好處是:處理某種指定的異常的代碼,只需編寫一次。作業沒寫完的同學到走廊罰站去,這符合我們處理問題的方式,不用挨個地告訴。? 4、無論是否拋出異常,finally塊封裝的代碼總能夠在try塊之后的某點執行。? 例子:? ? ? try {? ? ? ? ? return ;? ? ? ? ?}? ? ? finally{? ? ? ? ? System.out.print("You can't jump out of my hand!");? ? ? ? ?}? 甚至你在try塊內用return語句想跳過去都不可以!finally內的輸出語句還是執行了!別想逃出我的手掌心!? 5、catch塊和finally塊是可選的,你可以只使用try。但是這么做有意思嗎?? 6、推卸責任。Java允許你推卸責任,沒有必要從相應的try塊為每個可能的異常都編寫catch子句。Java2類庫中很多方法都會拋出異常,就是是把異常處理的權限交給了我們用戶。畢竟,Java不知道你的自行車被偷了之后,你會去報案還是會忍氣吞聲自認倒霉,或者偷別人的自行車。我們需要這種處理異常的自由度。? 7、調用棧。調用棧是程序執行以訪問當前方法的方法鏈。被調用的最后一個方法在棧的頂部,它將被最先執行完畢,然后彈出;第一個調用方法位于底部,也就是 main函數。在catch子句中使用printStackTrace()方法打調用棧信息是比較常用的定位異常的方法。 printStackTrace ()繼承自Throwable。? 8、異常的傳播。在一個方法A中,如果一個異常沒有得到處理,它就會被自動拋到調用A方法的B方法中。如果B方法也沒有處理這個異常,他就會被繼續依次向上拋,直到main方法。如果main也沒有理會它,那么異常將導致JVM停止,程序就中止了。你被同學揍了,先去告訴老師。老師不理你你就去告訴教導處主任,教導處主任也不管那只能告訴校長,校長還不管!沒有比他更大的了,于是你崩潰了,學業中止了…… 下面這段程序記錄了悲慘的輟學歷史:? ? ? class ExceptionDemo {? ? ? ? ? static void student() throws Exception{? ? ? ? ? ? ? teacher();? ? ? ? ? }? ? ? ? ? static void teacher() throws Exception{? ? ? ? ? ? ? schoolmaster();? ? ? ? ? }? ? ? ? ? static void schoolmaster() throws Exception{? ? ? ? ? ? ? throw new Exception();? ? ? ? ? }? ? ? ? ? public static void main(String[] args) {? ? ? ? ? ? ? try {? ? ? ? ? ? ? student();? ? ? ? ? }? ? ? ? ? catch (Exception e) {? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? }? ? ? ? ? ? ? ? ? }? ? ? }? 輸出結果是:? java.lang.Exception? ? ? at ExceptionDemo.schoolmaster(ExceptionDemo.java:9)? ? ? at ExceptionDemo.teacher(ExceptionDemo.java:6)? ? ? at ExceptionDemo.student(ExceptionDemo.java:3)? ? ? at ExceptionDemo.main(ExceptionDemo.java:13)? 可以看出函數的調用棧,一級一級地哭訴……? 9、異常的層次結構及Error。? ? ? ? ? Object? ? ? ? ? Throwable? ? ? Error? ? ? ? Exception? Throwable繼承自Object,Error和Exception繼承自Throwable。Error比較特殊,它對應于我們常說的不可抗拒的外力,房屋中介的合同上總有一條,如遇不可抗拒的外力本合同中止,返還乙方押金。我不安地問:不可抗拒的外力指什么?中介回答:比如戰爭、彗星撞擊地球等。 對Java來說Error是指JVM內存耗盡等這類不是程序錯誤或者其他事情引起的特殊情況。一般地,程序不能從Error中恢復,因此你可以能眼睜睜地看著程序崩潰而不必責怪自己。嚴格來講,Error不是異常,因為它不是繼承自Exception。? 10、誰之錯?一般地,異常不是我們程序員的錯,不是程序設計上的缺陷。比如讀取一個重要文件,這個文件被用戶誤刪了;正上著網呢,網線被用戶的寵物咬斷了。為了程序的健壯性,我們盡量考慮出現可能性大的異常,并處理,但我們不能窮盡。? 11、異常的捕獲之一。catch子句的參數是某種類型異常的對象,如果拋出的異常是該參數的子類,那么這個異常將被它捕獲。也就是說被拋出的異常不會精確地尋找最匹配的捕獲者(catch子句),只要是它的繼承結構的直系上層就可以捕獲它。 按照這個邏輯,catch(Exception e) 不就能捕獲所有的異常嗎?事實上,確實如此。但是一般地,不建議使用這種一站式的異常處理。因為這樣就丟失了具體的異常信息,不能為某個具體的異常編寫相應的異常處理代碼,失去了異常處理的意義。從哲學角度來講,具體問題要具體分析,能治百病的萬能藥一般都是無效的保健品。? Java在此處為什么這么設計呢?因為有另一種機制的存在,請看下條分解。? 12、異常的捕獲之二。當拋出一個異常時,Java試圖尋找一個能捕獲它的catch子句,如果沒找到就會沿著棧向下傳播。這個過程就是異常匹配。 Java規定:最具體的異常處理程序必須總是放在更普通異常處理程序的前面。這條規定再合理不過了,試想如果把catch(Exception e)放在最上面,那么下面的catch子句豈不是永遠不能執行了?如果你非要把更普遍的異常處理放在前面,對不起,通不過編譯!雖然編譯器不會這樣報錯: “It is so stupid to do like that!”……? 13、捕獲或聲明規則。如果在一個方法中拋出異常,你有兩個選擇:要么用catch子句捕獲所有的異常,要么在方法中聲明將要拋出的異常,否則編譯器不會讓你得逞的。? 方案一:處理異常? ? ? void ex(){? ? ? ? ? try{? ? ? ? ? ? ? throw new Exception();? ? ? ? ? } catch (Exception e) {? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? }? ? ? }? 方案二:拋出去? ? ? void ex() throws Exception{? ? ? ? ? throw new Exception();? ? ? }? 比較一下行數就知道了,在代碼的世界里推卸責任也是那么簡單,一個throws關鍵字包含了多少人生哲理啊……現實生活中我們有很多角色,兒女、父母、學生、老師、老板、員工……每個人都占了幾條。可是你能盡到所有責任嗎?按照古代的孝道,父母尚在人世就不能遠行。 各種責任是有矛盾的,顧此失彼啊。? 但是這條規則有個特例。一個繼承自Exception名為RuntimeException的子類,也就是運行時異常,不受上述規則的限制。下面的代碼完全能編譯,只不過調用之后在運行時會拋出異常。? ? ? void ex(){? ? ? ? ? throw new RuntimeException();? ? ? }? 14、throw和thrwos關鍵字。throw用在方法體中拋出異常,后面是一個具體的異常對象。throws用在方法參數列表括號的后面,用來聲明此方法會拋出的異常種類,后面跟著一個異常類。? 15、非檢查異常。RuntimeException、Error以及它們的子類都是非檢查異常,不要求定義或處理非檢查異常。Java2類庫中有很多方法拋出檢查異常,因此會常常編寫異常處理程序來處理不是你編寫的方法產生的異常。這種機制強制開發人員處理錯誤,使得Java程序更加健壯,安全。? 16、自定義異常類型。覺得現有的異常無法描述你想拋出的異常,ok!Java允許你自定義異常類型,只需要繼承Exception或者它的子類,然后換上有個性的名字。? ? ? class NotEnoughMoney extends Exception {? ? ? ? ? public NotEnoughMoney() {}? ? ? ? ? public NotEnoughMoney(String msg) { super(msg); }? ? ? }? 希望大家在生活里不要拋出類似的異常。? 17、重新拋出異常。一個很無聊的話題,純粹的語法研究,實際意義不大。當catch子句捕獲到異常之后可以重新拋出,那么它所在的方法必須聲明該異常。? ? ? void ex() throws Exception{? ? ? ? ? try {? ? ? ? ? ? ? throw new Exception();? ? ? ? ? }? ? ? ? ? catch (Exception mex) {? ? ? ? ? ? ? throw me;? ? ? ? ? }? ? ? ? ?}? 18、異常處理機制的效率。待補充……? 19、終止與恢復模型。異常處理理論上有兩種模型:? 一、終止模型。錯誤很關鍵且無法挽回,再執行下去也沒意義,只能中止。“羅密歐,我們分手吧!”“好吧,朱麗葉!”? 二、恢復模型。經過錯誤修正重新嘗試調用原來出問題的方法。“羅密歐,我們分手吧!”“朱麗葉,我錯了!請再原諒我一次吧!”“好的,再原諒你最后一次!”? 顯然我們更喜歡恢復模型,但在實際中,這種模式是不易實現和維護的。? 例子:用戶輸入了非法的字符,分別按照兩種模式處理? 一、終止模型。輸出出錯信息而已,一旦用戶手一抖眼一花你的代碼就崩潰了? ? ? double number;? ? ? String sNumber = "";? ? ? try {? ? ? ? ? BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));? ? ? ? ? sNumber = bf.readLine();? ? ? ? ? number = Double.parseDouble(sNumber);? ? ? ? ?} catch (IOException ioe) {? ? ? ? ? System.err.println("some IOException");? ? ? } catch (NumberFormatException nfe) {? ? ? ? ? System.err.println(sNumber + " is Not a legal number!");? ? ? }? ? ? //System.out.println(number);? ? 二、恢復模型。小樣!不輸入正確的數據類型就別想離開!? ? ? double number = 0;? ? ? String sNumber = "";? ? ? while(true){? ? ? ? ? try {? ? ? ? ? ? ? BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));? ? ? ? ? ? ? sNumber = bf.readLine();? ? ? ? ? ? ? number = Double.parseDouble(sNumber);? ? ? ? ? ? ? break;? ? //如果代碼能執行到這一行,就說明沒有拋出異常? ? ? ? ? } catch (IOException ioe) {? ? ? ? ? ? ? System.err.println("some IOException");? ? ? ? ? } catch (NumberFormatException nfe) {? ? ? ? ? ? ? System.err.println(sNumber + " is Not a legal number!");? ? ? ? ? }? ? ? }? ? ? System.out.println(number);? ? 直到用戶輸入正確的信息才會被該代碼放過。這是一種簡單的恢復模型的實現,挺耐看的,我很喜歡!? ?20、try、catch、finally內變量的作用域和可見性。? 在try塊內定義的變量,它在catch或者finally塊內都是無法訪問到的,并且在整個異常處理語句之外也是不可見的。 補充一點初始化:第一個例中最后一句被注釋掉了。number是在運行時由用戶輸入而初始化的,但是在編譯時刻并沒有初始化,編譯器會抱怨的。? ?21、輸出異常信息。捕捉到異常之后,通常我們會輸出相關的信息,以便更加明確異常。? ? ? catch (Exception mex) {? ? ? ? ? System.err.println("caught a exception!");? ? ? }? 用標準錯誤流System.err比System.out要好。因為System.out也許會被重定向,System.err則不會。? 22、更高級的話題我會補充上的,但是我的肚子拋出了Hungry異常,我必須catch然后調用eat()方法補充能量。昨晚的魷魚蓋澆飯很好吃…? ? 讀取配置文件:?
?
package myapp.src;
?
import java.io.IOException;
import java.util.Properties;
?
/**
?* @author xing.gexing E-mail:xing.gexing@aliyun-inc.com
?* @version 創建時間:Oct 30, 2012 9:46:53 PM 類說明
?*/
public class ReadConf {
? ? private String filename;
? ? private Properties properties;
?
? ? /**
? ? ?* @param args
? ? ?*/
? ? public ReadConf() {
? ? ? ? this.filename = "config.property";
? ? ? ? this.properties = new Properties();
? ? ? ? try {
? ? ? ? ? ? properties.load(ReadConf.class.getResourceAsStream(filename));
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? // TODO Auto-generated catch block
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
?
? ? /**
? ? ?* @return the filename
? ? ?*/
? ? public String getFilename() {
? ? ? ? return filename;
? ? }
?
? ? /**
? ? ?* @param filename
? ? ?*? ? ? ? ? ? the filename to set
? ? ?*/
? ? public void setFilename(String filename) {
? ? ? ? this.filename = filename;
? ? }
?
? ? /**
? ? ?* @return the properties
? ? ?*/
? ? public Properties getProperties() {
? ? ? ? return properties;
? ? }
?
? ? /**
? ? ?* @param properties
? ? ?*? ? ? ? ? ? the properties to set
? ? ?*/
? ? public void setProperties(Properties properties) {
? ? ? ? this.properties = properties;
? ? }
?
? ? public static void main(String[] args) {
? ? ? ? // TODO Auto-generated method stub
? ? ? ? ReadConf readConf = new ReadConf();
? ? ? ? System.out.println(readConf.getProperties().getProperty("endpoint"));
?
? ? }
?
}
?配置文件:?
?
?
endpoint=http://10.230.205.88:61085?
?
?
?
?…