第一章 java語言概述css
1.1 java語言的發展簡史html
1990末: sun公司「Green計劃」(James Gosling領導) ----目的是智能家電編寫一個通用嵌入式控制系統,爲此建立oakjava
1992夏天: "Green計劃"完成新平臺的部分功能 python
1992年11月: "Green計劃"被轉爲"FirstPerson有限公司"-一個sun的全資子公司,致力於建立一個高度互動的設備linux
1994夏天: 互聯網瀏覽器給Oak帶來信的生機,Gosling開始對Oak進行小規模的改造git
1994秋: WebRunner完成,Oak改名爲java程序員
1995初: Sun發佈java語言,公開源代碼 ,applet小程序風github
1996初: Sun發佈jdk1.0,包括jre(API,JVM,發佈技術等)和jdk(javac等)正則表達式
1997.2.18: 發佈jdk1.1,增長JIT編譯器算法
1998.12: Sun發佈jdk1.2/jsp/servlet/EJB等規範,將java分紅j2se,j2ee,j2me三個版本 ----最重要的jdk版本
2002.2: jdk1.4 ----最成熟的一個版本,出現各類開源框架
2004.10: jdk1.5 ----增長了泛型/加強for循環/可變數量型參/註釋/自動拆箱和裝箱
目錄 2006.12: jdk1.6
2007.11: Android問世
2009.4.20: Oracle收購sun(java和solaris)
2011.7.28:Oracle發佈jdk1.7
1.2 java的競爭對手即各自優點
1.2.1 c#: 和java由90%的重疊度,依賴windows平臺,具備許多windows特性
1.2.2 ruby: 擁有Roby on Rails這個MVC框架,簡潔,是與開發中小型應用
1.2.3 python: 高可擴展性/清晰的語法
1.3 java程序運行機制
1.3.1 高級語言的運行機制
1.3.2 java程序的運行機制和jvm
1.4 開發java的準備
1.4.1 下載和安裝java 7的jdk
1. jre和jvm的關係
jre包含:類加載器,字節碼校驗器以及大量的基礎類庫
2. 爲何不安裝公共jre
公共jre是一個獨立的jre系統,系統上任何一個程序均可以使用公共jre,網頁上的applet不多了,不必。jdk中包含的jre就夠用了。
1.4.2 設置path環境變量
1. 用戶變量與系統變量的區別: 用戶變量只對當前用戶有效,系統變量對全部用戶有效。系統變量比用戶變量優先級高。
1.5 第一個java程序
1.5.1 編輯java程序源代碼
1.5.2 編輯java程序
1. 爲和不須要指定.class文件的名稱
1.5.3 運行java程序
$ mkdir -p ~/git/github/practice/read/classfile; cd ~/git/github/practice/read/classfile
$ vim HeloWorld.java
$ javac -d classfile/ HelloWorld.java ---- -d 指定編譯文件放置的目錄
$ java -classpath classfile/ HelloWorld ---- -classpath 指定搜索的目錄
1.5.4 根據classpath環境變量定位類
1. jdk1.4以前須要設置CLASSPATH環境變量: .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar ----指定jvm運行時搜索當前路徑和那兩個jar包,由於那兩個jar中有必需的編譯/運行工具
2. 後來的jre會自動搜索當前目錄下的類文件,使用java的編譯和運行工具時系統也會自動加載那兩個jar包中的java類。
3. 運行時指定搜索路徑
$ java -classpath dir1;dir2;...;dirN java類名 ----win下在多個目錄中搜索的方式
$ java -classpath dir1:dir2:...:dirN java類名 ----linux下
1.6 java程序的基本規則
1.6.1 java程序的組織形式
1. java程序都必需以類的形式存在;
2. main方法做爲程序的入口的形式是固定的;
3. 沒有main方法的class HelloWorld{}這個最小的類是正確的,編譯能夠成功,但這個類不能做爲程序的入口來解釋執行;
4. 源文件的名字必需與public的類名相同,所以一個java源文件有且只有一個Public類;
1.6.2 java程序的組織形式
1.6.3 初學者容易犯的錯誤
1.7 垃圾回收機制
1.8 什麼時候開始使用ide工具
第二章 理解面向對象
2.1 面向對象
2.1.1 結構化程序設計簡介
2.1.2 程序的三種基本結構
1. 順序結構
2. 選擇結構
3. 循環結構
2.1.3 面向對象程序設計簡介
1. 是一種更加優秀的程序設計方法,它的基本思想是使用類/對象/繼承/封裝/消息等基本概念進行程序設計。
2.1.4 面向對象的基本特徵
1. 封裝: 將對象的實現細節隱藏起來,而後經過一些共有方法來暴露該對象的功能
2. 繼承: 是面向對象實現軟件複用的重要手段,當子類繼承父類後,子類做爲一種特殊的父類直接繼承父類的屬性和方法
3. 多態: 指的是子類對象能夠直接賦給父類對象,但運行時依然表現出子類的行爲特徵,這意味着同一個類型的對象在執行同一個方法時能夠有多種行爲特徵
2.2 UML(統一建模語言)介紹
2.2.1 用例圖
1. 開發階段: 需求分析階段
2. 用途: 幫助開發團隊以一種可視化的方式理解系統的需求功能
3. 元素: 用例(橢圓) + 角色(人形)
4. 注意: 描述系統的功能,方便和客戶交流;不要期望用例圖和系統的各個類之間由任何聯繫;不要將用例作的過多難以理解;儘量多地使用文字說明。
2.2.2 類圖
1. 表示方法
2. 三種基本關係:關聯(聚合/組合),泛化(繼承),依賴
2.2.3 組件圖
2.2.4 部署圖
2.2.5 順序圖
2.2.6 活動圖
2.2.7 狀態機圖
2.3 java面向對象特徵
2.3.1 一切都是對象
2.3.2 類和對象
第三章 數據類型和運算符
3.1 註釋
3.1.1 單行註釋和多行註釋
3.1.2 文檔註釋
1. api文檔是什麼
1. 生成java api的工具使用案例
$ javadoc -d apidoc -docencoding UTF-8 -charset UTF-8 -windowtitle 測試 -doctitle 學習javadoc工具測試 -header 個人類 -author -version TestDoc.java
-------------------------------------------------------------------------------------------------------------------------------------------------------
-d <dir>: 將生成的api文檔放在apidoc這個目錄下
-docencoding <name>: 指定輸出編碼的名稱
-charset <name>: 指定誇平臺查看文檔的字符集
-windowtitle <text>: 指定API文檔的瀏覽器窗口標題
-doctitle <html-code>: 指定html格式的文本,用於指定概述頁面的標題(針對源文件有多個包的狀況),這裏是單文件因此其實不該該加這個參數
-header <html-code>: 每一個頁面的頁眉
-version -author: 若是有的話,提取源代碼中的版本和做者信息(默認不提取)
----------------------------------------------------------------------------------------------------------------------------------------------------------
$ javadoc ----查看詳細幫助信息
2. 爲何要掌握查看api文檔的方法
3. 文檔註釋標記
1. 類/接口文檔註釋:
@see: "參見",用於指定交叉參考的內容
@deprecated: 不推薦使用的方法
@author: 做者信息
@version: 指定源文件的版本
2. 方法/構造器文檔註釋
@see: "參見",用於指定交叉參考的內容
@deprecated: 不推薦使用的方法
@param: 方法的參數說明信息
@return: 方法的返回值說明信息
@throws: 拋出的異常,和exception同義
@exception: 拋出異常的類型
3. Field文檔註釋
@see: "參見",用於指定交叉參考的內容
@deprecated: 不推薦使用的方法
3.2 標識符和關鍵字
3.2.1 分隔符
3.2.2 標識符規則
3.2.3 java關鍵字
3.3 數據類型分類
3.4 基本數據類型
3.4.1 整數: byte,short,int,long
3.4.2 java 7新增的二進制整數
1. 0b或0B打頭,後面只接二進制數字爲32位,後面還有L或l爲64位
2. 二進制相關
原碼: 直接將數字換算爲二進制
反碼: 反碼是原碼最高位不變,其他取反
補碼: 正數的補碼就是原碼,複數是其反碼+1
3.4.3 字符型(16位)
1. 表示方式
‘A’: 單個字符
‘\n’: 轉義字符
‘\uxxxx’: 十六進制編碼('\0000' - '\uFFFF')
2. 使用16位unicode字符集編碼
3.4.4 浮點型(IEEE754)
1. 使用二進制的科學計數法表示浮點數,沒法精確表示浮點數
2. 分類
float(32位): 符號位(1)+指數(8)+尾數(23)
double(64位): 符號位(1)+指數(11)+尾數(52)
3. 表示方法
float: 5.5f 或 5.5F
double: 5.5 或 5.5d 或 5.5D
4. 3個特殊的浮點數值
Double.POSITIVE_INFINITY或Floate.POSITIVE_INFINITY: 正無窮大(1/0)
Double.POSITIVE_INFINITY或Floate.NEGATIVE_INFINITY: 負無窮大(-1/0)
Double.NaN或Float.NaN: 非數(0.0/0.0 or (-2)^2)
3.4.5 java 7新增的數值中使用下劃線分隔
1. 舉例
int binVal = OB1000_0000_0000_0000_0000_0000_0000_0001;
float pi = 3.14_15_92_65_36;
2. 便於閱讀
3.4.6 布爾型
1. boolean: true or false
2. 用途
流程控制: if/while/for/do
三目運算符: ?:
3. 注意
1. boolean類型不能轉化爲其餘類型
2. 其它類型不能轉化爲boolean型
3 true和false不會直接轉換爲boolean類型
4. String str = true+"";
3.5 基本類型的類型轉換
3.5.1 自動類型轉換
1. 基本數據類型自動轉換: 範圍小的轉換成範圍大的
char
|
v
byte ->short->int->long->float->double
2. 基本數據類型自動轉換爲字符串類型: 從左到右,能計算就計算,和字符串鏈接即轉換爲字符串
3+4 + "Hello" -> "34Hello"
"hello" + 3 + 4 -> "hello34"
3.5f + "" -> "3.5"
3.5.2 強制類型轉換
1. 縮小轉換(溢出)
int - > byte: 從低位截取8位
3.5.3 表達式類型的自動提高
1. 無論有沒有int,運算中byte,short,char被提高爲int
2. 自動提高爲最高類型
3.6 直接量
3.6.1 直接量的類型
1. int(byte/short):
二進制: 0b10000 or 0B10000
八進制: 020
十進制: 16
十六進制: 0xf or 0Xf
2. long:
[int]l or [int]L
3. float:
534f or 5.34E2f or 534F or 5.34E2F
4. double:
534 or 5.34E2
5. boolean:
true or false
6. char:
'a' or '\n' or '\u0061'
7. String:
"hello"
8. null(特殊):
null: 能夠賦給任何引用類型
3.6.2 直接量的賦值
1. 常量池: 指的是編譯期間已肯定,並被保存到已編譯的.class文件中的一些數據。包括關於類/方法/接口中的常量,也包括字符串直接量。
2. java會確保每一個字符串常量只有一個,沒有副本
("hello"和"hel" + "lo"同樣,由於編譯時就進行了優化。)
3.7 運算符
3.7.1 算術運算符
1. 分類: "+", "-", "*", "/", "%", "++", "--"
2. 重點:
1. 」+「除了做爲數學加法運算符外還能夠做爲字符串鏈接符
2. 「++」或「--」只能用於變量,不能用於直接量,好比5++是錯誤的
3. 沒有平方,乘方運算符,能夠用庫中的方法實現(java.lang.Math)
3.7.2 賦值運算符
1. 變量 = 直接量;
2. 變量 = 變量;
3. 變量 = 變量 = ... =變量 = 直接量; ----java支持連續賦值,但會下降可讀性,所以不推薦
4. 加強的賦值表達式: += -= /= *= %= &= |= ^= >>= <<= >>>= ----擁有更好的性能
3.7.3 位運算符(注意計算機中的運算都是基於補碼的)
1. &: 按位與: 只有都爲1是才爲1
2. |: 按位或: 只要有一個爲1就爲1
3. ~: 按位非: 單目運算,1->0,0->1
4. ^: 按位亦或: 二者不一樣才爲1
5. <<: 左移運算符: 二進制補碼總體左移指定位數,空出的位補0
6. >>: 右移運算符: 二進制補碼總體右移,正數補0,複數補1
7. >>>: 無符號右移運算符: 二進制補碼總體右移,不管正負都補0
注意事項:
1. 只有整數類型能夠進行移位操做
2. byte/short/char類型進行移位操做時自動提高爲int
3. 32的類型移位超過32位時將對位數求餘,a>>33等價於a>>1
4. 64位類型(long)移位超過64位時將對64求餘
3.7.4 擴展後的賦值運算符
1. 分類:+= -= /= *= %= &= |= ^= >>= <<= >>>=
2. 擴展後的賦值運算符擁有更好的性能,底層機制更加健壯(a+=b和a=a+b底層是不同的)
3.7.5 比較運算符: > < == >= <= !=
1. 基本類型變量或直接量不能與引用類型變量或值進行==比較
2. boolean類型的值或變量不能與其它任何類型進行==比較
3. 不一樣引用類型變量之間沒有父子繼承關係也不能進行==比較
3.7.6 邏輯運算符
1. &&: 邏輯與
2 ||: 邏輯或
3. !: 邏輯非
4. &: 不短路與
5. |: 不短路非
6. ^: 亦或
(位運算符的操做數是整數類型,邏輯運算符操做的是boolean)
3.7.7 三目運算符
1. 結構: (expression)?if-true-statement:if-false-statement;
2. 舉例: String str = 3 > 5?"3大於5":"3小於5";
3.7.8 運算符的結合性和優先級
第四章 流程控制與數組
4.1 順序結構
4.2 分支結構
4.2.1 if條件語句
1. if(boolean)
{
expression;
}
2. if(boolean)
{
expression;
}
else
{
expresion
}
3. if(boolean)
{
expression;
}
else if(boolean)
{
expresion
}
...
else
{
expression;
}
4.2.2 java 7的switch分支語句
1. 結構
switch(expression)
{
case condition1:
{ ----可省略
statement;
break;
} ----可省略
...
case conditionN:
{
statement;
break;
}
default:
{
statement;
}
}
2. 控制表達式的數據類型
1. 傳統: byte, short, char, int
2. jdk 7: byte, short,char, int, java.lang.String
4.3 循環結構
4.3.1 while循環語句
while(boolean)
{
循環體;
}
4.3.2 do while循環語句
do
{
循環體;
}while(boolean);
4.3.3 for循環
1. 結構
for([init_statement]; [test_statement]; [iteration_statement])
{
statement;
}
2. [init_statement]初始化語句只在循環開始前執行一次
3. for循環圓括號中只有兩個";"是必需的,其它均可以省略,在語法上沒有問題: for(;;){}
4. 習慣選擇i,j,k做爲循環變量
4.3.4 嵌套循環
4.4 控制循環結構
4.4.1 使用break結束循環
1. 單純使用break: 結束所在的整個循環
2. 配合標籤使用: 結束外層循環
outer: ----一般緊跟在break後面的標籤必需在break所在的循環以前定義纔有意義
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 3; j++ )
{
System.out.println(i);
if(j == 1)
{
break outer;
}
}
}
4.4.2 使用continue結束本次循環
1. 單純使用continue: 跳出本次循環
2. 配合標籤使用: 直接跳過標籤所標識循環的剩下語句,從新開始下一次循環
4.4.3 使用return 結束方法
1. 無論潛逃多深,直接結束整個方法(不止循環體)
4.5 數組類型
4.5.1 理解數組: 數組也是一種類型
1. int[]是一種類型嗎?怎麼使用這種類型?
是。須要使用建立數組的語法。
4.5.2 定義數組
1. 定義方式
type[] arrayName; ----推薦
type arrayName[]; ----不推薦(最好永遠別這樣定義)
2. 注意: 定義數組不須要指定數組的長度,只是定義了一個引用變量,並未指向任何內存空間
4.5.3 數組的初始化
1. 能不能只分配內存空間,不賦初始值呢?
答:不行!無論以那種方式初始化數組,只要分配了內存空間,數組元素就有了初始值。哪怕是一個null值。
2. 初始化方式
1. 靜態初始化: 不知定數組長度,顯示指定每一個數組元素的初始值,由系統決定數組的長度。
int[] a; ----先定義
a = new int[]{1, 2, 3, 4} ---再初始化
int[] b = new int{5, 6, 7, 8} or int[] b = {5, 6, 7, 8} ----定義的同時初始化
2. 動態初始化: 初始化時程序員只指定數組長度,由系統爲數組元素分配初始值
Object[] obj = new String[9];
系統肯定初始值的方式:整數類型(0),浮點數(0.0),字符類型('\u0000'),boolean(false),類/接口/數組(null)
3. 不要進行數組初始化時既指定數組的長度,又指定每一個數組元素的值
4.5.4 使用數組
1. 爲何要我記住這些異常信息?
4.5.5 for each循環
1. 結構
for(type valName : arrayName/collectionName)
{
//valName自動迭代數組或集合中的每一個元素
}
2. 若是但願循環中改變數組元素的值,不要使用foreach循環
4.6 深刻數組
4.6.1 內存中的數組
1. 爲何有棧內存和堆內存之分?
4.6.2 基本類型數組的初始化
4.6.3 引用類型數組的初始化
4.6.4 沒有多維數組
1. 我是否能夠將數組元素指向另一個數組來擴展成多爲數組?
4.6.5 操做數組的工具類
4.6.6 數組的應用舉例
4.7 本章小結
第五章 面向對象(上)
5.1 類和對象
5.1.1 定義類
構造器不是沒有返回值嗎?爲何不能用void修飾?
答:簡答的說,這是java的語法規定。實際上類的構造器是有返回值的,當咱們我能用new關鍵字來調用構造器時,構造器返回該類的實例,能夠把這個類的實例當成這個類的返回值。須要注意的是,不能在構造器顯式使用return 返回當前類的對象,由於構造器的返回值是隱式的。
5.1.2 對象的產生與使用
1. 產生: 建立對象的根本途徑是構造器,經過new關鍵字來調用某個類的構造器便可建立這個類的實例
Persion p; //先定義引用
p = new Persion(); //後建立
or
Persion p = new Persion();
5.1.3 對象/引用和指針
Persion p = new Persion(); ///產生兩個東西,指向Persion實例的p變量,和一個Persion實例
5.1.4 對象的this引用
1. 老是指向調用該方法的對象
2. 兩種形式
在構造器中: 引用該構造器正在初始化的對象
在方法中: 引用調用該方法的對象
3. 在方法中調用該類另外一個方法是經常生省略this
調用static修飾的成員時省略主調: 默認使用該類做爲主調
調用沒有static修飾的成員時省略主調: 默認使用this做爲主調
4. 使用場景
1. 在構造器中訪問成員變量,恰巧該成員變量與構造器中定義的一個變量重名,能夠用this指定
2. 在方法中return this: 表示返回調用該方法的對象自己。
5.2 方法詳解
5.2.1 方法的所屬性
1. 爲何說java中的方法是二等公民?c中的方法是一等公民?
1. 方法不能獨立定義,方法只能在類體裏定義
2. 從邏輯上來講,方法要麼屬於這個類自己,要麼屬於某個對象
3. 永遠不能獨立執行方法,執行方法必須使用類或者對象做爲調用者
(明白了沒,java中只有類或者對象纔是一等公民)
5.2.2 方法的參數傳遞機制
值傳遞: 將實際參數的副本(複製品)傳入方法內,而參數自己不會受到影響
5.2.3 形參個數可變的方法
1. 舉例
public static void test(int a, String... books);//以可變個數形參定義方法
public static void test(int a, String[] books);//和上面比,調用方式不如上面靈活,但對books都是數組這一點是一致的
2. 注意
1. 長度可變的形參只能處於列表的最後
2. 一個方法只能包括一個長度可變的形參
3. 這個長度可變的形參既能夠傳入多個參數,也能夠傳入一個數組
5.2.4 遞歸方法
5.2.5 方法重載
1. 爲何方法的返回值類型不能用於區分重載的方法?
由於咱們調用方法的形式沒法反應被調用方法的返回值類型,系統沒法判斷到底調用那個方法。
2. 重載參數可變的方法
大部分時候,不推薦重載長度可變的方法,由於沒有太大的實際意義,並且容易減低可讀性。
5.3 成員變量和局部變量
5.3.1 成員變量和局部變量
0. 定義
成員變量: 成員變量就是方法外部,類的內部定義的變量。
局部變量: 局部變量就是方法或語句塊內部定義的變量。
(局部變量的數據存在於棧內存中。棧內存中的局部變量隨着方法的消失而消失。成員變量存儲在堆中的對象裏面,
由垃圾回收器負責回收。)
1. 變量分類圖
| 實例Field(不以static修飾)
| 成員變量——|
| |類Filed(以static修飾)
全部變量——|
| |形參(方法簽名中定義的變量)
|局部變量 ——|方法局部變量(在方法內定義)
|代碼塊局部變量(在代碼中定義)
2. 初始化狀況
| 實例Field:-------------
| 成員變量——| |----無須顯示初始化(系統會在這個類的準備階段或建立實例的階段進行默認初始化,見4.5.3.2.2)
| | 類Filed:---------------- 但對引用類型來講調用前必需初始化,由於默認爲null
全部變量——|
| | 形參: 無須顯式初始化,在調用該方法時由方法的調用者完成初始化
|局部變量 ——| 方法局部變量: 必需顯式初始化
| 代碼塊局部變量: 必需顯式初始化
3. 生命週期
| 實例Field: 隨實例的存在而存在
| 成員變量——|
| | 類Filed: 隨類的存在而存在
全部變量——|
| | 形參: 在整個方法內有效
|局部變量 ——| 方法局部變量: 從定義的地方生效,到該方法結束時失效
| 代碼塊局部變量: 從定義的地方生效,到該代碼塊結束時失效
4. 變量命名問題
1. 一個類內不能定義兩個同名的成員變量,實例成員變量或類成員變量都不能夠;
2. 一個方法內不能定義同名的局部變量,即便一個是代碼塊局部變量一個是方法局部變量也不行;
3. 容許局部變量和類變量重名。這是局部變量會覆蓋成員變量;
4. 若是想在方法或塊中調用類成員變量,可使用類名.變量名,若是調用實例成員變量,可使用this.變量名或實例名.成員變量名的方式。
5.3.2 成員變量的初始化和內存中的運行機制
1. 初始化的時機和位置(這裏的初始化指的是:類在用new建立其第一個實例時初始化)
(這裏不包括final修飾的狀況)
|基本數據類型: 在堆中那個對象中分配內存(若是沒有顯示初始化,將給默認值)
|實例Field——|
| |引用類型: 若是是第一次使用這個引用類型,會首先在堆中初始化這個類,建立類對象;若是沒有經過
| new顯示初始化該引用類型,這個引用變量對應null;顯式初始化後將在堆中分配該引用變量
| 引用另一個實例的內存空間。但這個空間再也不引用變量所在的對象的空間中,而是另一
| 個新開闢的空間。(String類是個特例,能夠經過new之外的方式初始化,這種狀況後面單獨
| 討論)
成員變量—|
| |基本數據類型: 只在必要時進行初始化,存儲在靜態域(方法區)中
|類Filed——|
|引用類型: 只在必要時初始化,存儲在靜態域(方法區)中
2. java虛擬機的懶加載(lazy-load)時機
1. 建立類的實例
2. 調用類的靜態方法
3. 操做類的很是量靜態字段(非final static)
4. 調用特定的反射方法
5. 初始化一個類的子類
6. 指定一個類爲虛擬機啓動時的初始化類
3. final修飾成員變量(final也能夠修飾局部變量)
|基本數據類型: 在堆中那個對象中分配內存(若是沒有顯示初始化,將給默認值)
實例Field——|
|引用類型: 若是是第一次使用這個引用類型,會首先在堆中初始化這個類,建立類對象;若是沒有經過 **************************************************new顯示初始化該引用類型,這個引用變量對應null;顯式初始化後將在堆中分配該引用變量
引用另一個實例的內存空間。但這個空間再也不引用變量所在的對象的空間中,而是另一
個新開闢的空間。(String類是個特例,能夠經過new之外的方式初始化,這種狀況後面單獨
討論)
|基本數據類型: 只在必要時進行初始化,存儲在靜態域(方法區)中
類Filed——|
|引用類型: 只在必要時初始化,存儲在靜態域(方法區)中
4. String特例講解
1. 兩種建立實例的方法
String str1 = new String("abc"); ----和通常的引用類型沒有區別,在堆中建立對象,棧中建立引用變量
String str2 = "abc"; ----想在棧中建立str2引用變量,而後若是常量池中有"abc",則將地址給str2,若是沒有
將"abc"加入常量池後將地址賦給str2
2.
5. 常量池
常量池指的是在編譯期被肯定,並被保存在已編譯的.class文件中的一些數據。
5.3.3 局部變量的初始化和內存中的運行機制
1. 初始化的時機和位置
| 形參: 方法被調用過程當中將實參的值賦給形參時初始化內存空間(所在方法的棧內存)
局部變量 ——| 方法局部變量: 賦值時初始化內存空間(所在方法的棧內存)
| 代碼塊局部變量: 賦值是初始化內存空間
2. 特色
1. 局部變量定義後,必需通過顯式初始化後才能使用,系統不會爲局部變量進行自動初始化。這意味着直到程序
爲這個局部變量賦初始值時,系統纔會爲這個變量分配內存空間。
2. 與成員變量不一樣,局部變量不屬於任何類或實例,所以它老是保存在其所在方法的棧中。引用類型保存堆中實例的地址。
3. 局部變量質保存基本類型的值或對象的引用,所以局部變量所佔的內存區一般比較小。
5.3.4 變量的使用規則
5.4 隱藏和封裝
5.4.1 理解封裝
1. 隱藏類的實現細節,限制不合理訪問
2. 進行類型檢查,保證對象信息的完整性
3. 便於修改代碼,可維護性
4. 暴露方法,控制訪問和操做
5.4.2 使用訪問控制符
1. 三個訪問控制符 ,四個訪問控制級別
private(當前類訪問控制權限): 限制只能在類內訪問其field
默認(包訪問權限): 被相同包下的其它類訪問
protected(子類訪問權限): 同包的其它類或不一樣包的子類訪問
public (公共訪問權限): 能夠被全部類以恰當的方式訪問
2. 使用規則
private: 除被static修飾的和必需暴露的Field以外的絕大部分Field
protected: 僅但願被子重寫,不但願被外界直接調用的Field
public: 大部分外部類/構造函數等但願其它類自由調用的Field
5.4.3 package import和import static
1. package
1. 爲何使用package
java引入包機制,提供類的多層命名空間,用以解決類的命名衝突,類文件管理等問題。
2. 包管理機制是什麼
java容許將一組功能相關的類放在同一個package下,從而組成邏輯上的類庫單元。
1. 定義方式: 將一個類放在指定包下的方式
package packageName; ----java源程序的第一個非註釋行寫下,該文件中定義的全部的類都屬於這個包。
若是沒有指定package語句,則會處於默認包下
2. 編譯方式
javac -d . ClassName.java ----會自動創建文件層次結構來存放class文件
(java規定,位於包中的類,在文件系統中也必須有與包名層次相同的目錄結構)
3. 執行方式
java packageName.ClassName ----虛擬機裝載packageName.ClassName類時,會依次搜索CLASSPATH
環境變量指定的惡系列路徑中packageName文件夾,並在packageName
下查找是否包含ClassName.class文件。
注: 1. 同一個包中的類沒必要位於相同的目錄下,只要將路徑加入到CLASSPATH中就能夠;
2. 把生成的class文件放在某個目錄下並不會屬於同一個包,目錄名更不會成爲包名。
3. 如何正確使用包機制
1. 源文件裏使用package語句指定包名,一個源文件只能指定一個包,即只能有一個package語句
2. class文件必需放在對應的路徑下
項目文件夾
__________|____________
src classes
____|______ _____|_____
| ... ... | ... ...
com com
... ...
Hello.java Hello.class
2. import關鍵字
1. 使用方法
1. import com.github.eli.Test; ----導入com.github.eli這個包下的Test類
2. import com.github.eli.*; ----導入這個包下的全部類
3. import static com.github.eli.Test; --------導入com.github.eli這個包下的Test類下的全部static修飾的Field(類成員)
4. import static com.github.eli.*; ---- 導入這個包下的全部類的類成員
2. 做用
1. import: 能夠省略寫包名
2. import static: 省略些報名和類名
3. 衝突(必需使用全名的狀況)
1. import相同名稱的類時必需使用該類的全名
2. import static相同名稱的類Field時須要使用全名
4. 默認導入
java默認全部源文件導入java.lang包下的全部類
5.4.4 java的經常使用包
1. java.lang: 包含了java語言的核心類,如String,Math,System,和Thread類等,系統會自動導入這個包下的全部類;
2. java.util: 包含了java的大量工具類/接口和集合框架/接口,例如Arrays/List/Set等
3. java.net: 包含了java 網絡編程相關的類/接口
4. java.io: 包含了java輸入/輸出相關的類/接口
5. java.text: 包含了java格式化相關的類
6. java.sql: 包含了java進行JDBC數據庫編程相關的類/接口
7. java.awt: 抽象窗口工具集的相關類/接口,主要用於GUI
8. java.swing: Swing圖形用戶界面變成的相關類/接口,用於構建平臺無關的GUI程序
5.5 深刻構造器
5.5.1 使用構造器執行初始化
1. 構造器是java對象的重要途徑,是否是說構造器徹底負責java對象?
答: 不是!當程序員調用構造器而構造器尚未返回初始化的對象前,系統已經產生了一個對象並進行了默認初始化
,只是這個對象不能被外部程序訪問,只能在構造器中經過this來引用,當構造器執行完畢後,將對象做爲返回值
返回,一般還會賦給一個引用類型變量,從而讓外部程序訪問該對象。
2. 構造器的訪問權限
public: 由於構造器主要用於被其它方法調用,用以返回該類的實例,所以一般設置爲public訪問權限
protected: 只要用於被子類調用
private: 阻止其它類建立該類的實例
注: 一般建議爲java類保留無參數的構造器
5.5.2 構造器重載
1. 爲何要用this來調用另外一個重載的構造器?
答: 爲了儘可能避免代碼重複出現。
2. 使用this調用重載的構造器
this(name, color); ----1. 只能在構造器中使用
2. 必需做爲構造器執行體的第一個語句
3. 系統會根據this後括號內的實參來調用形參列表與之對應的構造器
5.6 類的繼承
5.6.1 繼承的特色
1. 經過extends關鍵字來實現,實現繼承的類被稱爲子類,被繼承的類成爲父類(基類/超類);
2. java子類不能得到父類的構造器;
3. 子類只能有一個直接父類,若是沒有顯式指定直接父類,默認擴展(繼承)java.lang.Object,可見
java.lang.Object是全部類的直接或間接父類。
5.6.2 重寫(覆蓋)父類的方法
(重寫的規則)
1. 「兩同」: 方法名相同,參數列表相同;
2. 「兩小」: 子類方法返回值類型應比父類方法返回值類型更小或相等,子類方法聲明拋出的異常
類型應比父類方法聲明拋出的異常類型更小或相等。
3. 「一大」: 子類方法的訪問權限應比父類方法的訪問權限更大或相等
注:
1. 覆蓋方法和被覆蓋的方法要麼都是實例方法要麼都是類方法,一個是類方法,一個是實例方法會發生編譯錯誤;
2. 若是父類方法具備private訪問權限,則該方法對其子類是隱藏的,所以其子類沒法訪問該方法,也就沒法重寫該
方法;若是子類「重寫」了該方法,只不過是在子類中定義了一個新方法;
3. 子類覆蓋了父類方法後,子類對象沒法訪問父類的方法;
4. 在子類的方法中調用父類被覆蓋的方法的方式:
1. 調用被覆蓋的實例方法: super.方法名()
2. 調用被覆蓋的類方法: 父類名.方法名() ----和在與這個父類沒有繼承關係的類中調用方式同樣
5.6.3 super限定
1. super用於限定子類的對象調用從父類那裏繼承的是實例Field(注意不能是類Field);
2. 重載(overload)和重寫(override)
1. 重寫和重載放在一塊兒比較沒有太大的意義,由於重寫發生在同一個類中的同名方法(包括繼承來的方法)之間,
重載發生在父類和子類的同名方法之間;
3. 在某個方法中訪問某個field而沒有顯式指定調用者的查找順序
1. 方法中的局部變量;
2. 當前類的Field;
3. 直接父類的Field -> 上溯全部父類的Field - > ... -> java.lang.Object
注: 1. 當程序建立一個子類對象時,系統不只會爲該類中定義的實例變量分配內存,也會爲它從父類繼承的到的全部
實例變量分配內存,即便是同名的實例變量也會分別分配內存;
2. 子類中定義的和父類中同名的實例變量會隱藏父類的實例變量,但不會覆蓋,系統依然會爲被陰藏的實例對象
分配內存,這就是爲何用super能夠訪問到父類被隱藏的實例變量的緣由。
5.6.4 調用父類構造器
1. 父類構造器被調用的三種狀況(不管如何都會被調用)
1. 子類構造器執行體的第一行使用super顯式調用父類構造器,系統將根據super調用的實參列表調用父類對應
的構造器;
2. 在子類構造器的執行體的第一行使用this顯式調用本類中重載的構造器,系統根據this後的參數列表調用對應的構造
器。調用本類中另外一個構造器時會調用父類的構造器;
3. 子類構造器中既沒有this也沒有super,系統會在執行子類構造器以前,隱式調用父類無參數的構造器。
問: 爲何我建立java對象時從未感受到java.lang Object類的構造器被調用過?
答: 由於自定義的類從未顯式調用過java.lang.Object類的構造器,即便顯式調用java.lang.Object中的構造器,也只能調用
那個默認的構造器,不會輸出任何內容。
5.7 多態
(多態的本質:java引用變量的編譯時類型和運行時類型不一致。)
5.7.1 多態性
1. 表現多態: 父類引用變量調用子類重寫父類的方法: 編譯時類型是父類,運行時類型是子類,當把子類對象賦給父類引用變
量(系統自動向上轉型)後,表現子類的特徵;
2. 不表現多態的狀況: 父類引用變量調用子類中隱藏(不是覆蓋)父類Field的Field
3. 編譯出錯的狀況: 父類引用變量調用子類中定義的方法或Field(未重載或覆蓋)
5.7.2 引用變量的強制類型轉換
1. 基本類型之間的轉化只能在數值類型之間進行,數值類型與布爾類型之間不能轉換;
2. 引用類型之間的轉化只能是在具備繼承關係的兩個類型之間。特別地,若是想把父類對象轉換成子類對象,則父類變量必需引用的是子類實例才能夠。
5.7.3 instanceof運算符
1. 用法
Object obj = "abc";
if(obj instanceof String) { ----前一個操做數是一個引用類型變量,後一個操做數一般是一個類或接口
String str = (String)obj;
System.out.println("obj是String類型"):
}
2. 做用: 用於在強制類型轉換前,判斷前面的對象是不是後面的類或其子類/接口的實現,保證代碼更加健壯。
5.8 繼承與組合
5.8.1 使用繼承的注意點
(繼承帶來高度複用的同時嚴重破壞了父類的封裝性。)
1. 減輕繼承的反作用
1. 儘可能隱藏父類的內部數據(private修飾Field);
2. 不要讓子類能夠隨意訪問/修改父類的方法;
3. 儘可能不要在父類的構造器中調用被子類重寫的方法: 由於調用者默認是this,最終將調用子類的重寫後的方法;
4. 若是想設計成最終類,不想被繼承,使用final修飾類;
2. 合適須要派生新類設爲場景
1. 子類須要額外增長屬性;
2. 子類須要增長本身獨有的行爲方式。
5.8.2 利用組合實現複用
1. 什麼組合
爲了實現複用又要避免破壞服用對象的封裝性,能夠在將服用對象做爲一個Field組合到派生類中,能夠重載構造函數來實現初始化。
2. 繼承和組合
總之,繼承表達的是一種"是(is a)"的關係,組合表達的是「有(has a)」的關係。
問: 使用組合關係來實現複用時須要建立兩個animal對象,是否是一位着使用組合關係對系統開銷更大?
答: 不會,沒有本質的差別。由於當建立一個子類的實例時,不只要爲子類Field分配內存空間,還要爲其父類Field分配內存空間。
5.9 初始化塊
5.9.1 使用初始化塊
1. 語法格式
[修飾符]{ ----只能是static或沒有
//初始化塊的可執行代碼
...
}
2. 執行時機: 當java建立一個對象時,系統先爲全部實例Field分配內存(前提是該類已經加載過了),接着對實例變量初始化:
先執行初始化塊或聲明Field是指定的初始值,再執行構造器裏指定的初始值。
5.9.2 初始化塊和構造器
1. 初始化塊是構造器的補充,老是在構造器執行前執行;
2. 初始化塊是一段固定的代碼,不接受參數,也沒法被顯式調用;
3. 使用static修飾能夠對整個類進行初始化。
5.9.3 靜態初始化塊
1. 執行時機
系統將在類初始化階段執行靜態初始化塊,而不是在建立對象時才執行。所以老是必普通初始化塊先執行。
2. 使用陷阱: 靜態初始化塊(類初始化塊)屬於類的靜態成員,不能訪問非靜態成員。
注: 類的初始化
1. java加載並初始化某個類時,老是保證類的全部父類所有加載並初始化。
2. 當JVM第一次使用(懶加載)某個類時,系統會在類的準備階段爲該類的全部靜態Field分配內存;在
初始化階段則初始化靜態成員,執行順序與在代碼中的排列順序相同。
第六章 面向對象(下)
6.1 java 7加強的包裝類
1. jdk的8包裝類(關於類的詳細內容見API)
Byte(byte) Short(short) Integer(int) Long(long) Character(char) Float(float) Double(double) Boolean(boolean)
2. 包裝類與基本類型之間的轉換(以float)
1. jdk1.5以前
Float ff = new Float(4.56);//基本類型想包裝類型轉換
float f = ff.floatValue();//包裝類型向基本類型轉換
2. jdk1.5增長的自動拆箱/裝箱功能
Float ff = 4.56;//自動裝箱
float f = ff;//自動拆箱
Object boolObj = true; //自動封裝爲Boolean類型而後賦給boolObj
注意事項:
1. 對基本類型來講,自動拆箱/裝箱只能發生在同種數據類型和對應的包裝類(或對應包裝類的父類)之間;
2. 基本類型/包裝類型與字符串之間的轉換(部分藉助了對應包裝類的靜態方法)
(由於自動拆箱裝箱功能的存在)
1. 基本類型(包裝類型)->字符串類型:
方式一: String類提供了多個重載的valueOf()方法,用於將基本數據類型轉換成字符串;
方式二: String s = 3+"";
2. 字符串類型->基本類型(包裝類型)
方式一: 利用包裝類提供的Xxx(String s)構造器,若是字符串沒法轉化成對應的基本類型會報異常,特別的對
boolean來講,"true"不分大小些會轉化成true,其它字符串一概轉化成false;
方式二: 除了Character,其它7中包裝類都提供了parseXxx(String s)靜態方法;
3. 基本類型與包裝類型的比較: 直接取出包裝類包裝的數值來進行比較
4. 包裝類型之間的比較
1. 狀況一: 包裝類型其實是引用類型,指向同一個對象是返回true
2. 狀況二: Interger包裝類的實現方式是這樣的,緩衝一個Interger[]類型的數組,包裝-128-127,其它的纔會單首創
建Interger對象,所以,-128-127這個範圍內的包裝類型不管建立多少次都引用相同的地址
3. jdk7加強了包裝類的功能:
1. 爲全部包裝類提供了一個靜態的compare(xxx vall, xxx val2)來比較兩個基本類型的大小;
2. 爲Character包裝類增長了大量工具方法對一個字符基尼吸納給判斷(見API)
問: java爲何要對這些數據進行緩存呢?
答: 將一些建立成本大,須要頻繁使用的對象緩存起來,從而提升程序的運行性能。
6.2 處理對象
6.2.1 打印對象和tostring()方法
1. 幹什麼用的
返回該對象「自我描述信息」:「類名+@+hashcode」值,用以告訴外界該對象的狀態信息
2, 什麼時候調用該方法
1. 和字符串作鏈接運算時自動調用;
2. 須要返回對象的描述信息時(必要的話能夠想重寫它)。
6.2.2 ==和equals方法
1. 區別
==: 判讀引用是否相等(要求兩個對象的類型相同或有父子繼承關係)
equals(): Object提供的一個實例方法(和==功能同樣),全部引用變量均可以調用這個方法判斷與其它對象是否相等。
重寫該方法能夠能夠自定義兩個對象相等的規則。(片面說equals()是判斷值是否相等是錯誤的)(一般要求兩個對象是同一個類的實例)
2. 特例:String
String s = new String("hello"); //會建立兩個對象,「hello」直接量在常量池中,同時有個對象在堆內存中
String ss = "hello"; //要麼直接引用常量池中的"hello",要麼在常量池中加入"hello"而後引用
String重寫了equals()方法,判斷標準是字符串序列是否相同
常量池: 專門用於管理在編譯期間肯定並被保存在已編譯的.class文件中的一些數據。它包括類,方法,接口中的常量,還包括字符常量
3. 重寫equals()方法的規則
1. 自反性
2. 傳遞性
3. 一致性
4. x.equals(null)必定返回空(前提是x != null)
問: 判斷obj是不是person類的實例時爲何不用obj instanceof person來判斷呢?
答: 使用obj instanceof person時,obj引用對象的類型是person或persion的的子類就能夠。判斷對象是不是某個類型使用
obj.getClass() == Persion.class更合適。
6.3 類成員
6.3.1 理解類成員
1. 是什麼
static關鍵字修飾的成員就是類成員。類成員在類初始化是初始化,生命週期和類自己相同,屬於整個類,不屬於單個實例。
2. 有哪些/怎麼用
(java類有5中成員(Field,方法,構造器,初始化塊,內部類(接口,枚舉)),能夠做爲類成員的由4種(構造器除外))
1. 類Field: 能夠經過類或對象來訪問,但經過對象訪問實際還未委託給類訪問,null對象引用同樣能夠訪問類Field;
2. 類方法: 和類Field類;
3. 類初始化塊: 在類的初始化階段,系統會調用該類的初始化塊對類進行初始化,。一旦初始化結束,靜態初始化塊
永遠不會得到執行的機會。
4. 內部類(後面章節討論)
3. static關鍵字重要規則和緣由
類成員不能訪問實例成員。由於類成員是屬於類的,類成員的做用域比實例成員的做用域更大,徹底可能出現類成員已經初始化
完成而實例成員尚未初始化的狀況,若是容許類成員訪問類成員將會引發大量錯誤。
6.3.2 單例(singleton)類
1. 爲何
有些時候容許其它類自由建立該類的兌現更沒有任何意義,還可能形成系統性能的降低(頻繁建立/回收對象形成的系統開銷);
2. 是什麼
若是一個類只能爲其建立一個實例,則這個類被成爲單例類。
3. 怎麼做
1. 把該類的構造器使用private修飾。從而把該類的全部構造器隱藏起來;
2. 提供一個public static的方法,用於建立該類的對象並返回這個對象;
3. 建立一個類Field緩存已經建立的對象,不然沒法知道是否建立過對象。
實做:【1】
6.4 final修飾符
(final可修飾類/變量/方法,表示類/變量/方法不可改變。)
6.4.1 final成員變量
1. 使用方法: final修飾的成員變量必需顯式地指定初始值,且只能在一處進行,系統不會對final變量進行隱式初始化。
final 類Field: 必需在靜態初始化塊或聲明該Field時指定初始值
final 實例FIeld: 必需在非靜態初始化塊,聲明該Field或構造器中指定初始值
2. 提示
final 類Field不能在普通初始化塊中指定初始值,由於類Field在類初始化階段已經被初始化了,普通初始化塊不能對其從新賦值;
final 實例FIeld不能在靜態初始化塊中指定初始值,由於靜態初始化塊是靜態成員,不能訪問實例變量。
6.4.2 final局部變量
1. 初始化方式: 和普通局部變量的差異只在於只能賦值一次
(final修飾的形參不能進行顯式賦值操做)
6.4.3 final修飾基本類型變量和引用類型變量的區別
final修飾基本類型變量: 被修飾的變量不可改變
final修飾引用類型變量: 被修飾的變量對應的對象能夠改變,但被修飾的變量的值(地址)不能改變
6.4.4 可執行宏替換的final變量
1. 什麼是宏替換: 在編譯階段編譯器會把程序中用到「宏變量」的地方直接替換成該變量的值
2. 如何實現「宏變量」(同時知足三個條件)
1. 使用final修飾符修飾;
2. 在定義該final變量時指定了初始值;
3. 該初始值在編譯時就能夠肯定下來(也就是說初始值是算數表達式或字符串連接運算也不要緊)
6.4.5 final方法
1. 特色/爲何
final修飾的方法不可被重寫。出於某些緣由,不但願子類重寫父類的某些方法,便可以使用final修飾這些方法。
2. private final方法
在子類中試圖重寫父類的final方法會發生編譯錯誤,但由於子類沒法重寫父類的private方法,相應的「重寫」父類
的private final方法並不會出錯,由於這種狀況只是在子類定義了一個方法,不是真的重寫。
6.4.6 final類
1. 特色/爲何
final修飾的類不能夠被繼承。子類方法能夠改變父類方法的一些實現細節會致使一些不安全的因素,final類能夠避免這種狀況。
6.4.7 不可變類
1. 特色/爲何
不可邊類的意思是建立該類的實例後,實例的Field不可改變。不可變類在某種意義上比通常的類更加安全。
2. 如何自定義不可變類
1. 使用private和final修飾符來修飾該類的FIeld
2. 提供帶參數構造器,用於根據傳入參數來初始化類裏的Field
3. 僅爲該類的Field提供getter方法,不要爲該類的FIeld提供setter方法,由於普通方法沒法修改final修飾的Field.
4. 若是有必要,重寫Object類的hashCode和equals方法,要保證equals方法判斷爲相等的對象的hshcode也相等。
(若是要設計一個不可變類,尤爲要注意其引用類型Field,若是引用類型Field的類是可變的,就必需採起必要的措施來保護該Field
所引用的對象不會被修改,這樣才能才能建立真正的不可邊類。)
6.4.8 緩存實例的不可變類
6.5 抽象類
6.5.1 抽象方法和抽象類
1. 是什麼: 用abstrace關鍵字修飾的方法和類
(知足的規則)
1. 抽象類必需使用abstract修飾符來修飾,抽象方法也必需用abstract來修飾,抽象發發不能由方法體;
2. 抽象類不能經過new關鍵字實例化,即便抽象類不包含抽象方法也不;
3. 抽象類能夠包含Field/方法(普通方法和抽象方法均可以)/構造器/初始化塊/內部類/枚舉類6中成分。抽象類的構造器不
能用於建立實例,主要用於被其子類調用;
4. 含有抽象方法的類(包括直接定義了一個抽象方法;繼承了一個抽象方法,但沒有徹底實現父類包含的抽象方法,以及
實現了一個接口,但沒有徹底實現父類包含的抽象方法3種狀況)只能被定義成抽象類。
2. 注意
1. 有得有失: 抽象類能夠包含抽象方法,抽象類不能用於建立實例;
2. 抽象方法和空方法體不一樣: public abstract void test(); ----抽象方法 public void test(){} ----空方法體
3. abstract不能用於修飾:
Field: 沒有抽象成員變量,抽象類裏的Field只能是普通Field
局部變量: 沒有抽象變量,只能是普通變量
構造器: :抽象類裏定義的構造器只能是普通構造器,提供給子類調用
任何static修飾的方法: static修飾的方法屬於類自己,若是被abstract修飾將沒有方法體,被類調用必然出錯,所以
static和abstract不一樣時出現
final修飾的方法: abstrac修飾的類只能被繼承,即必須由子類重寫方法。而final修飾的類不能被繼承,final修飾的方法
不可以被重寫。所以final和abstract永遠不能同時使用。
private修飾的方法: abstract修飾的方法必需被子類重寫纔有方法體,而private修飾的方法不能被繼承和重寫,所以
private和abstract不能在一塊兒
6.5.2 抽象類的做用: 模板模式簡介
(模板模式的規則)
1. 抽象父類能夠只定義須要使用的某些方法,把不能實現的部分抽象爲抽象方法,留給子類去實現。
2. 父類中能夠包含其它系列方法: 這些方法既能夠由父類實現,也能夠由子類實現。父類提供的方法只是一個通用算法,可能需
要依賴子類的輔助。
6.6 更完全的抽象: 接口
6.6.1 接口的概念: 接口是從多個類似類中抽象出來的規範,接口不提供任何實現,一般是定義一組共用方法。接口體現的是規範和實
現分離的設計哲學。
6.6.2 接口的定義
【修飾符】 interface 接口名 extends 父接口1,父接口2...
{
零到多個常量定義...
零到多個抽象方法定義...
}
規則:
1. 修飾符: public 或者省略(包訪問權限)
2. 接口名: 和類名採用相同的命名規則
3. 接口的繼承: 一個接口能夠由多個父接口,不能繼承類
4. 接口的成員:
Field(只能是常量): public static final
方法(只能是抽象實例方法): public abstract
內部類(包括內部接口/枚舉)定義: public
對比接口和類: 比類的成員少兩種,Field只能是常量,方法只能是抽象方法。
5. 接口成員的修飾符: 接口裏定義的內部類/接口/枚舉類默認都採用public static 兩個修飾符,無論定義時是否
指定這兩個修飾符,系統都會自動用public static對他們進行修飾
6. 接口是一個特殊的類: 所以一個java源文件裏最多隻能有一個public接口,若是一個java源文件裏定義了一個
public接口,則該源文件名必須與該接口名相同。
6.6.3 接口的繼承
1. 多繼承概念: 接口的繼承和類繼承不同,接口徹底支持多繼承,即一個接口能夠有多個直接父接口。
2. 多繼承格式: 多父接口排在extends關鍵字以後,多個富姐口直接以英文逗號(,)隔開。
6.6.4 使用接口
1. 語法格式
【修飾符】 class 類名 extends 父類 implements 接口1, 接口2...
{
實體部分...
}
2. 接口的使用方式
1. 聲明引用類型變量: 接口不能用於建立實例,但能夠用於聲明引用類型變量,改變量引用的必需是其實現類的對象;全部的
接口類型的引用變量均可以直接賦給Object類型的引用變量,利用上轉型來實現的。
2. 被實現類實現(能夠當成繼承一個更加完全的抽象類)
(實現的意義)
1. 得到的成員: 得到所實現接口裏定義的常量Field/抽象方法/內部類和枚舉類定義;
2. 抽象方法: 必須實現繼承的接口裏的所有抽象方法,除非定義爲抽象類;
3. 實現接口方法時,必須使用public訪問控制修飾符,由於接口裏的方法都是public的,實現和繼承同樣,子類重寫或實現
類實現的方法只能更大或相等;
3. 錯誤使用方式: 接口不能顯式繼承任何類
6.6.5 接口和抽象類
1. 相同點
1. 被其餘類實現或繼承: 接口和抽象類都不能被實例化,他們都位於繼承樹的頂端,用於被其餘類實現和繼承;
2. 實現抽象方法: 接口和抽象類均可以包含抽象方法,實現接口或抽象類的子類都必須實現這些方法。
2. 不一樣點
1. 設計思想
接口: 接口體現的是一種規範。當在一個程序中使用接口是,接口是多個模塊間的耦合標準;當在多個應用程序間使用接口時
,接口是多個程序間的 通訊標準;
抽象類: 做爲系統中多個子類的共同父類,體現的是一種模板式設計,抽象類做爲多個子類的共同父類,能夠看成中間產品,
須要進一步完善。
2. 用法的差別
1. 方法
接口: 只能包含抽象方法,不能定義靜態方法,不包含以及提供實現的方法
抽象類: 能夠是普通方法(提供實現),能夠定義靜態方法
2. Field
接口: 只能是靜態常量Field
抽象類: 任何Field
3. 構造器
接口: 不包含構造器
抽象類: 包含構造器器(不用於建立對象,用於被子類調用完成抽象類的初始化)
4. 初始化塊
接口: 不包含
抽象類: 包含
5. 繼承/實現機制
接口: 能夠實現多個接口,你補java類單繼承的不足
抽象類: 類(包括抽象類)是單一繼承的
6.6.6 面向接口編程
1. 簡單工廠模式
2. 命令模式
6.7 內部類
(內部類簡分析)
1. 是什麼: 在某些狀況下,咱們吧一個類放在另外一個類的內部定義,這個定義在其餘類內部的類叫作內部類(嵌套類)。
2. 爲何
1. 內部類提供了更好的封裝,能夠把內部類隱藏在外部類以內;
2. 內部類能夠訪問外部類的私有數據,但外部類不能訪問內部類的實現細節;
3. 匿名內部類適合建立那些僅需建立一次的類。
3. 內部類的分類想
| 靜態內部類
|成員內部類|
| 非靜態內部類
內部類-|
|局部內部類
|匿名內部類
注: 1. 大部分時候,內部類做爲成員內部類定義;
2. 成員內部類是一種與Field,方法,構造器,初始化快類似的類成員(能夠用任意訪問控制符修飾)
3. 外部類和內部類的訪問控制權限比較
外部類(2個做用域): 同一個包(不加修飾符)和任意位置(public)
內部類( 4個做用域): 同一個類(private),同一個包(默認),父子類(protected),任何位置(public)
6.7.1 非靜態內部類
1. 外部類不容許直接訪問內部類的實例Field,由於外部類直接訪問內部類的實例Field時內部類對象沒有建立;
2. 外部類的靜態方法、靜態塊不能訪問非靜態內部類(甚至不能定義內部類對象或建立內部類對象);
3. 非靜態內部類不能包含靜態成員(包括靜態Field、靜態方法、靜態塊)
問: 非靜態內部類對象和外部類對象的關係是怎樣的?
答: 非靜態內部類必須寄存在外部類對象裏,而外部類對象中不必定有內部類的實例寄存其中。
6.7.2 靜態內部類 (優先使用靜態內部類)
1. 是什麼: 若是用static修飾一個內部類,則這個類屬於外部類自己,而不屬於外部類的某個對象,成爲類內部類或靜態內部類。
2. static能夠修飾外部類嗎?
static關鍵字不可修飾外部類,但可修飾內部類。
解析: static關鍵字的做用是把類的成員變成類相關的,不然就是實例相關的。外部類的上一級是包,咱們能夠說外部類
是屬於包的,經過static修飾沒有意義,內部類是外部類的成員,這是用static修飾纔有意義。
3. 行爲特徵
1. 靜態內部類能夠包括靜態成員,也能夠包括非靜態成員;
2. 根據靜態成員不能訪問非靜態成員的規則,靜態內部類(包括內部類的實例方法)不能訪問外部類的實例成員,只能訪問外部類的類成員;
3. 靜態內部類也能夠用於建立對象,靜態內部類是外部類的靜態成員,所以外部類的靜態方法、靜態初始化塊中可使用靜態內部類來定義變量、建立對象;
4. 外部類能夠經過靜態內部類的類名訪問靜態內部類的類成員或經過靜態內部類的對象訪問其實例成員;
5. 接口中定義的內部類默認使用public static修飾,若是指定修飾符也只能和默認相同,所以接口中的內部類只能是靜態內部類。
問題1: 爲何靜態內部類的實例方法也不能訪問外部類的實例屬性?
答: 由於靜態內部類對象不寄存在外部類對象中,而是寄存在外部類自己中。靜態內部類持有的是外部類的類引用而不是外部類的對象的引用,因
此沒法訪問實例相關的外部類實例屬性。
問題2: 接口裏是否能定義內部接口?
答: 能夠。但接口中定義的接口只能是public static修飾的,當被類實現時,實現類得到這個內部接口。一般不這樣使用接口,接口一般被做爲一
種公共規範。
6.7.3 使用內部類
(使用場景)
1. 在外部類中使用內部類(和使用通常類比較)
相同點:
1. 能夠直接經過內部類類名來定義變量,經過new調用內部類構造器建立實例;
2. 在外部類內部定義內部類的子類也沒有太大區別。
區別: 不能在外部類的靜態成員中使用非靜態內部類,由於靜態成員不能使用非靜態內部成員
2. 在外部類之外使用非靜態內部類
1. 訪問權限
(private修飾的內部類只能在外部類中訪問)
1. 省略訪問控制符: 只能被與外部類處於同一個包中的其它類訪問;
2. protected: 與外部類同包的類或外部類的子類;
3. public: 能夠在任何地方被訪問
2. 在外部類之外的類中定義內部類變量(靜態或非靜態)
OuterClass.InnerClass varNme; ----若是外部類有包名還應該增減包名前綴
3. 在外部類之外的類中建立內部類對象
調用構造器建立對象: OuterInstance.new InnerConstructor(); ----非靜態內部類對象,須要經過外部類對象調用非靜態內部類的構造器
建立非靜態內部類的子類:
class SubClass extends Out.In { ----子類繼承Out類的非靜態內部類In
public SubClass(Out out) {
out.super("hello"); ----建立非靜態內部類的子類時須要給構造函數傳遞外部類對象,而後在構造器中經過OuterInstance.super()調用父類的構造器
}
}
注: 非靜態類的子類不必定是內部類,它能夠是一個外部類。但非靜態內部類的子類的實例必須具備一個指向外部類實例
的引用。也就是說,若是有一個內部類子類的對象存在,則必定存在與之對應的外部類對象。
4. 在外部類之外使用靜態內部類
調用構造器建立對象: new OuterClass.InnerConstructor(); ----靜態內部類是類相關的,建立內部類對象時無需外部類對象
建立靜態內部類的子類: class SubClass extends Out.In {} ----子類繼承Out類的非靜態內部類In,只要包外部類當成包空間便可
問: 既然內部類是外部類的成員,那麼是否能夠爲外部類定義子類,在子類中在定義一個內部類來重寫其父類中的內部類?
答: 不能夠!由於所處的外部類不一樣,子類中的內部類和父類中的內部類不會同名,也就沒法重寫。
6.7.4 局部內部類
1. 定義: 在方法內定義的內部類,僅在該方法內有效,不能使用static 和訪問控制符修飾。
2. class文件命名格式: OuterClass$NInnerClass ----比成員內部類多一個數字,由於同一個類中能夠有多個同名局部內部類,增長一個數字用以區分。
(局部成員的上一級程序單元都是方法而不是類,所以使用static沒有意義;其它程序單元永遠沒法訪問另外一個方法中的局部成員,因此不能用訪問控制符修飾。)
6.7.5 匿名內部類
1. 定義: 建立時當即建立一個對象,只使用一次,不能重複使用。
2. 格式: new 父類構造器(實參列表) | 實現接口(){
//匿名內部類的類體部分;
}
3. 規則:
1. 必須繼承一個父類或實現一個接口,但最多隻能繼承一個父類或或實現一個接口;
2. 不準將匿名內部類定義成抽象類,由於匿名內部類會當即建立對象;
3. 不能定義構造器,能夠定義實例初始化塊完成初始化;
4. 必須實現它的抽象父類或接口中的全部抽象方法(不然就變成抽象類);
5. 匿名內部類只能訪問用final修飾的外部類的局部變量
4. 建立匿名內部類的機制的區別(繼承父類和實現接口)
1. 構造器(不能顯式建立構造器)
實現接口: 只有一個隱式無參構造器,所以「new 接口名()"後名的()中不能有參數
繼承父類: 和父類的構造器類似,擁有相同的形參列表
6.7.6 閉包和回調
1. 閉包: 閉包是一種能被調用的對象,保存了建立它的做用域信息,能夠將非靜態內部類看成面向對象領域的閉包。
2. 回調: 內部對象能夠很方便地回調其外部類的Field,方法,這樣可讓編程更加靈活。
6.8 枚舉類: 實例有限並且固定的類
6.8.1 手動實現枚舉類
1. 設計方式
1. 經過private將構造器隱藏起來
2. 把這個類全部可能的實例都使用public static final修飾的變量來保存
3. 若是有必要,提供一個靜態方法,容許其它程序根據特定參數來獲取與之匹配的實例
6.8.2 枚舉類入門: java1.5以後增長了對枚舉類的支持
(和普通類比較)
1. 相同點: 能夠有本身的Field,方法,能夠實現一個或多個接口,能夠定義本身的構造器。一個java源文件最多隻能定義一個
public 訪問權限的枚舉類,且該java源文件也必需和該public枚舉類同名。
2. 區別
1. 繼承
普通類: 默認繼承java.lang.Object
枚舉類: 默認繼承java.lang.Enum(父類仍是Object),該類實現了java.lang.Serializable和java.lang.Comparable兩個接口
2. 被繼承
普通類: 能夠被繼承(除非用final修飾)
枚舉類: 不可被繼承,由於enum定義的類默認用final修飾(除非是抽象類)
3. 構造器
普通類: 構造器可使用三種訪問控制符修飾,默認使用public修飾
枚舉類: 只能使用你該private修飾,默認使用private修飾,強制只能使用private修飾
4. 實例
普通類: 通常能夠在任何地方用new建立
枚舉類: 全部實例必需在第一行顯式列出,不然這個枚舉類永遠沒法產生實例(系統會自動添加public static final修飾,無須程序員顯式添加)
5. 遍歷
普通類: 通常須要其它迭代器的協助
枚舉類: 全部枚舉類都提供了一個values方法,能夠方便地遍歷全部的枚舉值
3. 使用方法
1. 枚舉類語法格式示例
public enum SeasonEnum {
SPRING, SUMMER, FALL, WINTER; ----建立四個枚舉類實例,中間用","隔開,以";"結束
}
2. 調用方法: EnumClass.varible
SeasonEnum.SPRING ----以上面定義的枚舉類爲例
3. 迭代方法
for(Season s:SeasonEnum.values) {
//處理代碼
}
4. java.lang.Enum提供的方法
1. int compareTo(E o): 該方法用於與指定枚舉對象比較順序
2. String name(): 返回此實例的名稱
3. int ordinal: 返回枚舉值在枚舉類中的索引值(從0開始)
4. String toString(): 返回枚舉常量的名稱,和name()類似,但更經常使用
5. public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name): 返回指定枚舉類中的某個枚舉值
6.8.3 枚舉類的field/方法和構造器
1. Field
1. 原則: 枚舉類一般應該設置成不可邊類,Field最好用private final修飾,在初始化塊或構造器中完成初始化。
2. 建立帶初始化參數的枚舉值:MALE("男"), FEMALE("女");
2. 方法
1. 原則
普通方法: 此時全部枚舉值擁有相同的方法
抽象方法: 每一個枚舉值能夠經過匿名內部類的方式分別實現該方法
2. 經過匿名內部類建立枚舉值
MALE("男") {
public void info(){
System.out.prnitln("這個枚舉值表明男性!");
}
},
FEMALE("女") {
public void infp() {
System.out.println("這個枚舉值表明女性!");
}
};
問: 枚舉類不是用final修飾了嗎?怎麼還能派生子類呢?
答: 並非全部的枚舉類都使用final修飾。對於一個抽象枚舉類而言——只要包含抽象方法,就是抽象枚舉類,系統默認使用abstract
修飾,而不使用final修飾。
6.8.4 實現接口的枚舉類: 與普通類實現接口徹底同樣: 使用implements實現接口,實現接口裏包含的抽象方法。
6.8.5 包含抽象方法的枚舉類: 由不一樣的枚舉值提供不一樣的實現
注: 枚舉類中定義抽象方法時不使用abstract關鍵字將枚舉類定義成抽象類(由於系統會自動添加)。
6.9 對象與垃圾回收
(垃圾回收機制的特徵)
1. 只回收堆內存中的對象,不回收任何物理資源(數據庫鏈接/網絡IO等)
2. 程序沒法精確控制垃圾回收的運行,垃圾回收會在合適的時候發生
3. 垃圾回收任何對象以前會調用finalize()方法,該方法可能使對象復活而取消垃圾回收
6.9.1 對象在內存中的狀態
1. 可達狀態: 對象被建立並被一個以上的引用變量引用,則對象處於可達狀態;
2. 可恢復狀態: 若是某個對象再也不由任何引用變量引用,就進入可恢復狀態。finalize()方法進行資源清理後,
若是從新讓一個引用變量引用了這個對象,則進入可達狀態;不然進入不可達狀態。
3. 不可達狀態: 當對象與全部引用變量的關聯被切斷,且系統調用了全部對象的finalize()方法後對象沒有變成
可達狀態,則永久失去引用,進入不可達狀態。此時系統纔會回首對象佔用的資源。
建立以後 失去引用
起點 --------------->可達狀態------------------------>可回覆狀態 垃圾回收
<------------------------- -------------------------->不可達狀態------------>終點
從新得到引用 完全失去引用
6.9.2 強制垃圾回收: 程序只能控制一個對象什麼時候再也不被引用,不能控制其合適被回收
1. 兩種方式(只是通知系統進行垃圾回收,系統是否執行是不肯定的,大部分時候總會有必定效果)
1. 調用System類的gc()靜態方法: System.gc()
2. 調用Runtime對象的gc()實例方法: Runtime.getRuntime().gc()
2. 運行時打印每次垃圾回收是的提示信息
java -verbose:gc GcTest ---- -verbose:gc選項指定打印垃圾回收的提示信息
6.9.3 finalize方法: 方法返回時對象消失,垃圾回收機制開始執行,任何java類均可以重寫這個Object的方法
1. 特色
1. 永遠不要主動調用某個對象的finalize()方法,該方法應交給垃圾回收機制調用
2. finalize()方法合適被調用,是否被調用具備不肯定性,不必定會被執行
3. 當JVM執行可恢復對象的finalize()方法時,該對象或系統中其餘對象可能變爲可達狀態(how)
4. finalize()出現異常時,垃圾回收機制不會報告異常,程序繼續執行
注意: 因爲finalize()並不必定會被執行,所以若是想清理某個類打開的資源,不要放在finalize()中清理
2. 強制調用可恢復對象的finalize()方法
Runtime.getRuntime().runFinalization();
6.9.4 對象的軟/弱和虛引用
(java.lang.ref提供了三個類)
1. 強引用(StrongReference)
回收時機: 當一個對象被一個或一個以上的引用變量所引用時,它處於可達狀態,不可能被垃圾回收機制回收。
2. 軟引用(SoftReference)
回收時機: 當系統空間不足時,系統可能回首它。一般用於對內存敏感的程序中。
3. 弱引用(WeakReference)
回收時機: 無論內存是否充足,只要垃圾回收機制運行就會回收。
4. 虛引用(PhantomReference)
回收時機: 主要用於跟蹤對象被垃圾回收的狀態,除此以外和沒有引用效果至關。必需和引用隊列聯合使用。
注: 若是要使用這些特殊的引用類,就不能保留對對象的強引用,不然將不會發揮任何價值
6.10 修飾符的適用範圍
外部類/接口 | 成員屬性 | 方法 | 構造器 | 初始化塊 | 成員內部類 | 局部成員 | |
public | y | y | y | y | y | ||
protected | y | y | y | y | |||
包訪問控制符 | y | y | y | y | 看起來使用 | y | 看起來使用 |
private | y | y | y | y | |||
abstract | y | y | y | ||||
final | y | y | y | y | y | ||
static | y | y | y | y | |||
strictfp | y | y | y | ||||
synchronized | y | ||||||
native | y | ||||||
transient | y | ||||||
volatile | y |
注:
1. strictfp關鍵字的含義是FP-strict,精確浮點數。所修飾範圍內java編譯器的運行時環境會依照浮點規範IEEE-754來執行。
2. native關鍵字修飾的方法相似與一個抽象方法,將交由c來實現,程序中包含native方法意味着失去跨平臺能力。
3. 四個訪問權限控制符是互斥的。
4. abstract和(final,static,private)中任何一個都不能同時使用
6.11 使用jar文件
(jar)
1. 是什麼(Java Archive File)
Java的檔案文件,一種壓縮文件,和zip文件的區別是文件中默認包含了一個名爲META-INF/MANIFEST.MF的清單文件。
2. 爲何
1. 安全: 能夠進行數字簽名
2. 加快下載速度: 壓縮後的單個文件只需一個HTTP連接
3. 壓縮
4. 包裝性
5. 可移植性: 做爲Java平臺內部處理的標準,在各類平臺直接使用
6.11.1 jar命令詳解
1. 建立jar文件: jar cf test.jar test ----將test路徑下的所有內容生成一個test.jar文件,若是當前路徑中已有test.jar,覆蓋之,不顯示壓縮過程
2. 建立jar文件並顯式壓縮過程: jar cvf test.jar test
3. 不使用清單文件: jar cvfM test.jar test
4. 自定義清單文件: jar cvfm test.jar a.txt test ----在原清單文件基礎上增長a.txt中的內容到META-INF/MANIFEST.MF文件中
注:清單文件的格式(清單文件只是普通的文本文件)
1. 每行只能定義一個key-value對,不能由任何空格
2. 每組key-value對之間以": "(英文冒號後面跟一個英文空格)
3. 文件開頭不能由空行
4. 文件必需以一個空行結束
5. 查看jar包內容: jar tf test.jar
6. 查看jar包詳細內容: jar tvf test.jar
7. 解壓縮: jar xf test.jar
8. 帶提示信息解壓縮: jar xvf test.jar
9. 更新jar文件: jar uf test.jar Hello.class ----若是test.jar中由Hello.class則更新之,沒有則添加進去
10. 更新時顯式詳細信息: jar uvf test.jar Hello.class
6.11.2 建立可執行的jar包
1. 三種發佈方式
1. 使用平臺相關的編譯器將整個應用編譯成平臺相關的可執行性文件。一般須要第三方編譯器的支持。會喪失跨平臺性,甚至性能降低。
2. 爲應用編輯一個批處理文件
java package.MainClass ----運行程序的主類
start javaw package.MainClass ----不使用java的命令行窗口
3. 將一個應用程序製做成一個可執行的jar包
製做:
jar cvfe test.jar Test *.class ----將全部.class文件都壓縮到test.jar中,並指定使用Test類做爲程序的入口
運行:
java -jar test.jar ----使用java命令
javaw test.jar ----使用javaw命令
6.11.3 關於jar包的技巧
第七章 與運行環境交互
7.1 與用戶交互
7.1.1 運行java程序的參數
1. 解析main方法簽名(public static void main(String[] args){})
1. public修飾符: java類由jvm調用,爲了讓jvm能夠自由調用main方法,因此使用public修飾符將這個方法暴露出來。
2. static修飾符: jvm調用該方法時不會向建立該主類的對象,而後經過對象來調用該主方法。JVM直接經過該類來調用
主方法,所以使用static修飾該主方法。
3. void返回值: 由於該方法被jvm調用,返回值會返回給jvm,這沒有任何意義,所以main方法沒有返回值
4. 「String[] args」形參: main方法由jvm調用,所以由jvm賦值
2. 給mian方法傳遞參數: java 主類 第一個參數 第二個參數 第三個參數 ...
1. 舉例
java javaCrazyBook.ArgsTest aa bb cc "xiao li" ----傳遞字符串數組參數["aa", "bb", "cc" ,"xiao li"]給jvm(jvm是main的調用者)
2. 原則
1. java程序後緊跟一個或多個字符串,以空格隔開,jvm會依次將這些字符串賦給args數組元素
2. 若是參數自己包含空格,則應將參數用雙引號("")括起來
7.1.2 使用scanner獲取鍵盤輸入(也能夠講文件做爲輸入源)
1. 簡述: Scanner是一個基於正則表達式的文本掃描器,它能夠從文件、輸入流、字符串中解析出基本類型值和字符串值。Scanner提供了多
個構造器,不一樣的構造器能夠接收文件、輸入流、字符串做爲數據源,用於從文件、輸入流、字符串中解析數據。
2. 提供了兩個方法進行數據的掃描
1. hasNextXxx(): 是否還有下一個輸入項,其中Xxx能夠是Int、Long等表明基本數據類型的字串或Line。若是須要判斷是否還有下一個
字符串,則能夠省略Xxx。默認空格爲掃描的分隔符,遇到分隔符就認爲當前掃描的這一項結束,返回true。
經常配合while使用,若是下一項沒有輸入將會阻塞,等待輸入,直到得到下一項輸入爲止。
2. nextXxx(): 獲取下一個字符串或基本數據類型,若是類型不符會中斷程序。默認空格爲分隔符。
注: Scanner類提供useDelimiter(String pattern)實例方法設置自定義的分隔符,其中pattern是一個正則表達式。例如若是想程序
無論有沒有空格,每次讀取一行,能夠講"\n"做爲 分隔符。固然也能夠用hasNextLine()和nextLine()配合實現每次讀取一行。
7.1.3 使用BufferedReader獲取鍵盤輸入
(在jdk5中增長Scanner類以前的得到鍵盤輸入的方式)
1. 什麼是
BufferedRreader是java IO流中的一個字符、包裝流,必須創建在另外一個字符流的基礎之上。
2. 怎麼用
/*System.in是字節流,new InputStreamReader(System.in)將其包裝成爲一個字符流*/
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
/*逐行讀取鍵盤輸入,BufferedReader只能一行一行讀取用戶的鍵入,每行被當作一個String對象
沒法讀取基本輸入類型項*/
while((line = br.readLine()) != null){
System.out.println("用戶鍵盤輸入是:" + line);
}
7.2 系統相關
7.2.1 system類
1. 是什麼
System類表明當前Java程序的運行平臺,程序不能建立System類的對象,System類提供了一些類Field和類方法。
2. 具體用法(具體請查看api)
1. System類提供標準輸入、標準輸出、和錯誤輸出的類Field
System.in ---標準輸入(鍵盤),對應修改方法 System.setIn()
System.out ----標準輸出(屏幕),對應修改方法 System.setOut()
System.err ----錯誤輸出,對應修改方法 System.setErr()
2. 訪問環境變量、系統屬性的靜態方法
System.getenv() ----獲取全部的環境變量(返回Map對象)
System.getenv("JAVA_HOME") ----得到指定環境變量
System.getProperties() ----得到全部系統屬性(返回Properties對象)
System.getProperties(」os.name「) ----得到指定系統屬性
3. GC相關
System.gc() ----通知系統進行垃圾回收
Systeem.runFinalization() ----通知系統進行資源清理
4. 得到系統時間的方法
System.currentTimeMillis() ----返回與UTC1970.1.1午夜的世間差(毫秒),在某些操做系統不精確,由於,某些操做系統以幾十毫秒爲單位
System.nanoTime() ----返回與UTC1970.1.1午夜的世間差(納秒),大部分操做系統不支持納秒
System.identityHashCode(Object x) ----返回指定對象的精確hashcode值(根據對象的地址進行計算),惟一地標識該對象
5. 提供了加載文件動態連接庫的方法(主要對native方法有用)
System.loadLibrary(String libname) ----加載動態連接庫
System.load(String filename) ----加載文件
注:java程序完成諸如訪問操做系統底層硬件等特殊功能,須要藉助c爲java提供實現,而後用java調用之。步驟以下
1. java程序中聲明native方法,相似於abstract方法,只有方法簽名,沒有實現,生成一個class文件;
2. 用javah將上面的class文件編譯產生一個.h文件;
3. 寫一個包含上面的.h文件的.cpp文件實現native方法;
4. 將上面的.cpp 編譯成動態連接庫文件;
5. 在java中加載上面的動態連接庫文件,可用的加載方式:
System.loadLibrary(String libname)
Runtime.loadLibrary(String libname)
6. 在java程序中調用這個native方法。
7.2.2 runtime類
1. 是什麼
Runtime表明java程序的運行時環境,每一個java程序都有一個與之對應的Runtime實例,應用程序經過該對象與運行時環境相連。
應用程序不能建立本身的Runtime實例,但能夠經過Runtime.getRuntime()方法獲取與之關聯的Runtime對象
2. 具體用法
1. GC相關
Runtime.gc() ----通知系統進行垃圾回收
Runtime.runFinalization() ----通知系統進行資源清理
2. 提供了加載文件動態連接庫的方法(主要對native方法有用)
Runtime.loadLibrary(String libname) ----加載動態連接庫
Runtime.load(String filename) ----加載文件
3. 訪問jvm相關信息
(Runtime rt = Runtime.getRuntime();)
rt.availableProcessors() ----處理器數量
rt.freeMemory() ----空閒內存數
rt.totalMemory() ----總內存數
rt.maxMemory() ----可用最大內存
4. 單獨啓動一個進程運行操做系統的命令
(Runtime rt = Runtime.getRuntime();)
rt.exec("notepad.exe"); //運行記事本程序
注: Runtime提供了一系列exec()方法來運行操做系統的命令,詳見API.
7.3 經常使用類
7.3.1 object類
1. 簡介
Object類是java全部類、數組、枚舉類的父類,任何java對象均可以調用Object的方法。
2. Object的經常使用方法
1. boolean equals(Object obj): 判斷兩個對象是不是同一個對象,和==同樣,所以沒有太大價值。
2. protected void finalize(): 當失去全部引用時,垃圾回回收器調用該方法清理對象的資源。
3. Class<?> getClass: 返回該對象的運行時類。
4. toString(): 返回對象的字符串表示。顯示調用或系統自動調用(System.out.println()方法輸出一個對象或者與字符串進行鏈接運算時)。
5. wait(),notify(),notifyAll(): 控制線程。
6. protected clone(): 經過」自我克隆獲得當前對象的一個」淺拷貝「,即只會克隆該對象全部Field的值,不會對引用類型Field引用的對象也
進行拷貝。「該方法只能被子類重寫和調用。開發者能夠經過遞歸克隆實現」深拷貝「。
7.3.2 java 7新增的objects 類
1. 簡介: 一個工具類,提供一些工具方法來操做對象,這些工具方法大可能是「空指針」安全的。
7.3.3 String, StringBuffer和StringBuilder類
1. String: 不可變類(字符序列不可變,知道這個對象被銷燬)
1. 種類衆多的構造器(API)
2. 大量操做字符串對象的方法(API)
2. StringBuffer: 字符序列可變的字符串類(線程安全)
append()、insert()、reverse()、setChar()、setLength()等方法修改字符串序列;
toString() ----調用它的這個方法將其轉換成String
3. StringBuilder: JDK1.5後出現的字符串對象(線程不安全,性能略高)
7.3.4 math類
1. 簡介
Java提供Math類來完成一些複雜的運算,好比三角函數、對數運算、指數運算。Math類是一個工具類,構造器是private的,
全部的方法都是類方法。
7.3.5 java 7的threadLocalRandom與Random
1. Random: 該類專門用來生成一個僞隨機數。
1. new Random() ----默認使用當前時間做爲種子
2. new Random(Long long) ----指定一個Long型整數做爲種子,若是兩個實例使用相同的種子,並且按相同的順序調
用相同的方法,這些方法就會產生相同的僞隨機值。爲了不這種狀況推薦使用當前
時間做爲種子:」Random rd = new Random(System.currentTimeMilis()); 「 。
2. ThreadLocalRandom: JDK7新增的一個類,與Random用法基本類似,在併發環境鮮能夠減小多線程資源競爭,提高性能。
ThreadLocalRandom rand = ThreadLocalRandom.current() ----提供了一個current()靜態方法得到對象,這一點與Random不一樣
7.3.6 BigDecimal類: 爲了能精確表示、計算浮點數,Java提供了java.math.BigDecimal類
1. 建立BigDecimal對象
1. 提供了大量構造器用於建立BigDecimal對象,包括:
1. 基本數值型變量;
注: 不推薦使用new BigDecimal(double dou),有必定不可預知性,推薦替代方案:
BigDecimal.valueOf(double dou) 或 new BigDecimal(String dou)
2. 數字字符串;
3. 數字字符數組。
2. 提供了構造BigDecimal的靜態方法
BigDecimal.valueOf(double val)
BigDecimal.valueOf(long val)
BigDecimal.valueOf(long unscaledVal, int scale)
2. 對精確浮點數進行常規算數運算
add()、substract()、multiply()、divide()、pow()等實例方法
注: 程序中能夠定義一個工具類對浮點數進行精確計算,計算時就不用每次都將浮點數先包裝成BigDecimal。
7.4 處理日期的類
7.4.1 java.util.Date類: kdk1.0就開始存在的處理日期、時間的類,大部分構造器、方法已通過時,不推薦使用
1. 構造器(6個構造器-4個Deprecated = 2個可用的)
Date(): 生成一個表明當前日期的Date對象。該構造器調用底層的System.current TimeMillis()
得到long整數做爲日期參數。
Date(long date): 指定long整數(和GMT1970.1.1 00:00:00之間的時間差)
2. 方法(多數已經Deprecated,只剩下少數幾個方法)
boolean after(Date when): 測試該日期是不是在when以後
boolean before(Date when): 測試該日期是不是在when以前
int compareTo(Date anotherDate): 比較兩個日期的大小
boolean equals(Object obj): 當兩個日期表示同一時刻時返回true
long getTime(): 返回改時間對應的long型整數(和GMT1970.1.1 00:00:00之間的時間差,單位是毫秒)
void setTime(long time): 設置該Date對象的時間
注: Date中的不少方法已經不被推薦使用了,若是想對日期進行加減運算或者獲取指定對象中的年月日,
應該用Calender工具類。
7.4.2 java.util.Canlendar類
1. 說明: Calendar是一個抽象類,用來更好的處理日期和時間(替代java.util.Date)。
2. 使用方式
1. 建立Calendar對象(由於是抽象類,不能使用構造器建立實例對象)
static Calendar getInstance() ----使用默認的Locale和TimeZone
static Calendar getInstance(Locale aLocale) ----指定Locale
static Calendar getInstance(TimeZone zon) ----指定TimeZone
static Calendar getInstance(TimeZone zone, Locale aLocale) ----指定Locale和TimeZone
2. 訪問、修改時間日期的經常使用方法
void add(int field, int amount): 爲指定的日曆的字段增長或減去指定的時間量
int get(int field): 返回指定日曆字段的值
int getActualMaximum(int field): 返回指定日曆字段的最大值(好比月份是11)
int getActualMinimum(int field): 返回指定日曆字段的最小值(好比月份是0)
void roll(int field, int amount): 和add()相似,不過超過field字段的最大值也不會自動按照日曆規則使上級字段進位
void set(int field, int value): 將給定的日曆字段設置爲給定值
void set(int year, int mounth, int day): 設置Calendar對象的年、月、日三個字段的值
void set(int year, int mounth, int day, int hourOfDay, int minute, int second): 設置Calendar對象的年、月、日、時、分、秒
3. Calendar類注意點
1. add和roll的區別
(add(int field, int amount)和roll都是用來改變特定字段的值,amount爲正時增減某個字段的值,amount爲負時減小某個字段的值)
1. add的規則
1. 當修改的字段超出容許範圍時,會發生進位,上一級字段也會增大;
2. 若是須要下一級字段的值改變,會修正到變化最小的值
2. roll的規則
1. 當修改的字段超出容許範圍時,會發生進位,但上一級字段不會增大;
2. 同add
2. 設置Calendar的容錯性
1. 說明: Canlendar有兩種解釋日曆字段的模式(lenient和no-lenient模式)
lenient: 該模式下每一個字段能夠接受超出它容許範圍的值
no-lenient: 該模式下若是字段超出容許的值將跑出異常
2. 設置方法
ssetLenient(false) ----Calendar提供了了這個方法用於設置容錯性,參數爲false時將變爲no-lenient模式
3. set方法延遲修改: set方法修某個字段後該字段會當即改變,但Calendar對象所表示的時間不會當即改變,直到下次調用get()、
getTime()、getTimeMillis()、add()或roll()時纔會從新計算日曆的時間。
7.4.3 java.util.TimeZone類