配置java環境變量:html
JAVA_HOME:配置JDK的目錄java
CLASSPATH:指定到哪裏去找運行時須要用到的類代碼(字節碼)程序員
PATH:指定可執行程序的位置sql
LINUX系統(在" .bash_profile "下的環境變量設置)數據庫
JAVA_HOME=/opt/jdk1.5.0_06apache
CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar編程
PATH=$PATH:$JAVA_HOME/bin:.windows
export JAVA_HOME CLASSPATH PATH (將指定的環境變量聲明爲全局的)設計模式
windows系統:數組
右擊個人電腦-->屬性-->高級-->環境變量
Java的運行過程:
編譯:生成可執行文件,如C++中利用g++生成a.out,效率高,但不跨平臺
解釋:解釋器把源文件逐行解釋,跨平臺但效率不高
在java中:先編譯後解釋,把.java文件編譯成.class字節碼文件
Java源代碼文件(.java文件)--->
Java編譯器(javac)--->
Java字節碼文件(.class文件,平臺無關的)--->
Java解釋器(java),執行Java字節碼
Java的垃圾回收:
由一個後臺線程gc進行垃圾回收
虛擬機斷定內存不夠的時候會中斷代碼的運行,這時候gc才進行垃圾回收
缺點:不可以精確的去回收內存
java.lang.System.gc(); 建議回收內存,但系統不必定迴應,他會先去看內存是否夠用,夠用則不予理睬,不夠用纔會去進行垃圾回收
內存中什麼算是垃圾:
再也不被引用的對象(局部變量,沒有指針指向的)
java的安全性:
沙箱機制:只能作沙箱容許的操做
經過下面環節,實現安全
加載有用的類文件,不須要的不加載
校驗字節碼,查看容許的操做
查看代碼和虛擬機的特性是否相符
查看代碼是否有破壞性
查看是否有違規操做,如越界
查看類型是否匹配,類型轉換是否能正確執行
源程序:
package mypack; //至關於一個目錄
public class HelloWorld{
public static void main(String[] args){
System.out.println(「Hello World」);
}
}
注:
一、文件名必須和public修飾的類名一致,以.java做爲文件後綴,若是定義的類不是public的,則文件名與類名能夠不一樣。
二、一個.java文件中能夠有多個class,可是隻有一個public修飾的類。
三、java源代碼文件編譯後,一個類對應生成一個.class文件
四、一個java應用程序應該包含一個main()方法,並且其簽名是固定的,它是應用程序的入口方法,能夠定義在任意一個類中,不必定是public修飾的類
編譯:javac -d . HelloWorld.java
含有包的類,在編譯的時候最好用上面的格式,-d指的是讓該類生成的時候按照包結構去生成," . "指的是在當前路徑下生成
若是不用上面的格式,也能夠用javac HelloWorld.java,可是須要注意的是包結構就要由本身去創建,而後將生成的.class文件放到該目錄下
執行:java mypack.HelloWorld
將字節碼文件交給Java虛擬機去解釋執行
須要注意的事,必須使用包名.類名去解釋執行
包(package):把源文件放在目錄下
因爲工程的須要,將不一樣的源文件放在不一樣的目錄下,從而引入了包。
包能夠看做就是一個存放java源文件的目錄。
在源碼中聲明一個包名:package p;(只能放在第一行,且最多隻能是一行)
若是指定多層包,那麼在包名之間咱們能夠用.做爲分隔符:package p1.p2.p3.p4;
用「javac HelloWorld.java –d 絕對路徑」,編譯後生成的字節碼文件就會放在指定的包結構下
執行該程序須要用" java 包名.類名 "
引進包中的某個類:import 包名.類名;
引進包中的全部類:import 包名.*;
註釋:
// 單行註釋, 到本行結束的全部字符會被編譯器忽略
/* */ 多行註釋, 在/* */之間的全部字符會被編譯器忽略
/** */ 文檔註釋, java特有的,在/** */之間的全部字符會被編譯器忽略
能夠用javadoc把java源程序中這種註釋抽取出來造成html頁面(只有寫在包,類,屬性,方法,構造器,引入以前的註釋才能夠進行抽取)
標識符:
命名規則:
(1) 由字母、數字、下劃線、$組成,不能以數字開頭
(2) 大小寫敏感
(3) 不得使用java中的關鍵字和保留字
關鍵字:都是小寫的,jdk1.2多了strictfp(精準浮點型),關鍵字 jdk1.4多了assert(斷言)關鍵字, jdk1.5多了enum(枚舉) 關鍵字
隨着學習進度,會慢慢接觸到的
true、false、null嚴格說不該該算關鍵字,應稱其爲保留字更合適
習慣:
(1) 標識符要符合語義信息
(2) 包名全部字母小寫
(3) 類名每一個單詞首字母大寫,其它小寫 //TarenaStudent
(4) 變量和方法:第一個單詞小寫,從第二個單詞開始首字母大寫 //tarenaStudent
(5) 常量:全部字母大寫,每一個單詞之間用" _ "鏈接
基本數據類型:8種
1) 整型
byte 1B 8位 -128到127
short 2B 16位 -2^15到(2^15)-1
int 4B 32位 -2^31到(2^31)-1
long 8B 64位 -2^63到(2^63)-1
2) 浮點類型
float 4B 32位
double 8B 64位
3) 字符類型
char 2B 16位
4) 布爾型 1B
boolean false/true
注:
一、Java中的自動類型提高問題。
1)、正向過程:從低字節到高字節能夠自動轉換。
byte->short->int->long->float->double
2)、逆向過程:從高字節到低字節用強制類型轉換。
例:int a = (int)4.562;
注:逆向轉換將丟失精度。
二、boolean:只有true和false。
三、char:Java中用" \u四位十六進制的數字 (即便在註釋中出現\u,後面若是跟的不是4個數字,也會報錯)"表示將字符轉換成對應的unicode編碼,字符類型要用單引號括起來。
四、黙認浮點類型爲double,float數據類型有一個後綴爲" f "或" F "。
五、long類型有一個後綴,爲" l " 或者" L "
引用數據類型:
類、接口、數組
引用類型 變量名 = new 引用類型名(參數); //new後面通常跟的都是類的構造器
成員:寫在類體括號裏面的
內存空間的分配:
內存分爲:
棧:存放簡單數據類型變量(值和變量名都存在棧中),存放引用數據類型的變量名以及它所指向的實例的首地址
堆:存放引用數據類型的實例
局部變量:不是聲明在類體括號裏面的變量
(1)必需要先賦值,後使用,不然通不過編譯,局部變量沒有默認初始化值
(2)做用範圍:定義開始到定義它的代碼塊結束
(3)同一範圍內,不容許2個局部變量命名衝突
參數傳遞時,簡單類型進行值轉遞 (參數進行傳遞時都會先去棧中生成一個副本的,使用結束後釋放)
自動類型提高:
byte a = 1;
byte b = 2;
a = a+b; //編譯出錯自動類型提高成int
a += b; //自加沒有自動類型提高問題
類型自動提高規則:
a和b做某種運算
a和b中有double,結果就是double
a和b中有float,結果就是float
a和b中有long,結果就是long
除此以外,結果都是int
把高字節轉成低字節,須要做強制類型轉換. byte c=(byte)a+b;
移位運算符:效率最高
>> 有符號右移,補符號位
移負數位,則將該數值加32後再進行移位
數值的2進制是按照補碼保存的
>>> 右移後高位都補0
邏輯運算符:
&/|也能夠做爲邏輯運算符
&& 先判斷前面一個條件,若是爲假,則不用計算後一個條件
|| 先判斷前面一個條件,若是爲真,則不用計算後一個條件
" + "運算符:
兩個操做的對象是數值時,是加法
若是有一個是字符串時,則是字符串的鏈接
流程控制語句:
同Core C++
switch中的變量類型只能是byte、 short、int、char四種類型以及enum類型
switch(exp) exp 能夠是整形表達式或者enum類型數據
數組:
聲明數組:
數組能如下列形式聲明:
類型[] array;
類型 array[];
注:
JAVA中推薦用:類型[] array;
一個數組是一個對象
聲明一個數組沒有建立一個對象
聲明時不用指定長度
建立數組:
建立基本數據類型數組:int[] i = new int[2];
建立引用數據類型數組:Student[] s = new Student[100];
數組建立後其中的元素有初始值
類型 黙認值
byte 0
short 0
int 0
long 0l
float 0.0f
double 0.0d
char \u0000
boolean false
reference types null
注:
建立時必定要指定長度
int[] i2=new int[]; //error
初始化數組:
聲明、建立、初始化分開:
int[] i; //定義數組
i = new int[2]; //分配空間
i[0] = 0; //初始化
i[1] = 1;
聲明、建立、初始化在同一時間 :
int[] i = {0,1}; //顯示初始化 {}中有幾個值,則數組長度爲幾
Student[] s = {new Student(),new Student()};
注: int[] i=new int[]{1,2,3}; //後面[]中不能夠寫數值
int[] i1=new int[3]{1,2,3}; //error
二維數組:(實際上是一個一維數組,它的每個元素又是一個一維數組)
int[][] i1 = new int[2][3];
int[][] i4 = {{1,1,1},{2,2,2},{3,3,3}};
int[][] i3 = new int[][3]; //不容許高維沒分配空間而先給低維分配空間
int[][] i2 = new int[2][];
i2[0] = new int[2];
i2[1] = new int[3];
數組長度:
數組的屬性length
數組長度一旦肯定,不可改變
int[] i = new int[5]; 則i.length= 5
數組拷貝:
系統類System提供的
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src: 源數組
srcPos: 從源數組哪一個位置開始拷貝(位置指的是元素的下標)
dest: 目標數組
destPos: 拷貝的元素放到目標數組的起始位置
length: 拷貝多少個
數組排序:
本身實現一個排序方法來進行排序
或者調用java.util.Arrays.sort(Object o)
類和對象:
類:主觀抽象,是對象的模板,能夠實例化對象----具備相同屬性和行爲的對象的集合。
習慣上類的定義格式:
package xxx;
import xxx;
public class Xxxx{
屬性 ······;
構造器 ······;
方法 ······;
}
區分實例變量以及類變量,二者都有初始值,或在定義時候初始化或者在構造函數中初始化,而局部變量沒有初始值,必須定義時候初始化。
定義屬性:實例變量
格式:[ 修飾符 ] 類型 變量名 [ = ? ]
實例變量定義在類中但在任何方法以外。
實例變量有默認值:各類各樣的0。(同數組)
實例變量的做用域至少在本類內部,受訪問控制符的限制。
在重合做用域,實例變量和局部變量容許有命名衝突,「局部優先」。
定義方法:
格式: [ 修飾符 ] 返回類型 方法名( 參數列表 ) [ throws 異常 ] { ······ }
java中全部參數都是值傳遞。
當沒有值返回時,返回類型必須被定義爲void。
返回類型必須與方法名相鄰,其餘修飾符能夠調換位置。
構造器:
在建立對象的過程當中調用的方法。
構造器沒有返回類型。
構造器的名字與類名相同。
格式爲:[ 修飾符 ] 類名( 參數列表 ){ },修飾符能夠是private、 protected、 default、private
在一個對象的生成周期中構造器只用一次,由系統自動調用,不容許手工調用。
程序員沒有提供一個構造器,系統會自動提供一個無參的構造器。
得到對象的方式:
經過new(在堆空間中申請分配空間),new 類名(),能夠經過這種形式或的一個對象,這時的對象是沒法使用,必須把他的地址存放進一個對象變量纔可以使用。
例如 :
Car c=new Car();
注意:
最好在寫類時提供一個無參的構造器。
默認是自帶一個無參構造器,但若是手動寫了一個帶參數的構造器,必須加上一個無參構造器。
this關鍵字:
this是個隱式參數,表明當前對象;
publie class Student{
private String name;
public void setName(String name){
this.name=name; //this.name爲當前對象的成員變量
}
}
若是某個構造方法的第一個語句具備形式this( ··· ),那麼這個構造方法將調用同一類中的其餘構造方法。
注意:
在構造器中this(...)必須放在該構造器的第一行。
this不能出如今靜態方法裏面
類、對象、實例三者的關係:
類:是對象的模板,能夠實例化對象
對象:類的個體
實例:實現的對象
student s;
s=new student();
其中 Student爲類,s爲對象,new Student()爲實例,s賦值後也是實例了。
方法重載:
方法名相同,參數表不一樣,不考慮返回值類型(但最好仍是使返回類型一致)。
編譯器根據參數,選擇一個方法,若是沒有徹底匹配的,對於參數表採用「向上就近匹配原則」,但不容許模棱兩可。
方法重載屏蔽了一個對象的同一類方法因爲參數不一樣所形成的差別。
封裝:
類的屬性加private修飾符,來限制只可以在類的內部進行訪問,有效的保護數據。
對於類中的私有屬性,要對其給出一對方法getXxx(),setXxx()訪問私有屬性,保證對私有屬性的操做的安全性。
方法公開的是方法的聲明,即只須知道參數和返回值就能夠調用該方法,隱藏方法的實現的細節。
一個對象和外界的聯繫應當經過一個統一的接口,應當公開的公開,應當隱藏的隱藏。
繼承:
父類到子類是從通常到特殊的關係。
泛化:將不一樣子類中的共性抽象成父類的過程。
特化:在原有父類的基礎上加入一些個性的過程。
原則:父類放共性,子類放個性。
繼承的關鍵字:extends
Java只支持單繼承:一個類最多隻有一個直接的父類。
方法覆蓋:
方法名:相同
參數表:相同
訪問限制符:相同或者更寬
返回值類型:相同或者子類返回的類型是父類返回的類型的子類(在JDK5.0之後)
拋出的異常:不能比父類更寬。
super關鍵字:
super()表示調用父類的構造器
super()也和this()同樣必須放在方法的第一句
super()和this()不能同時出現
super能夠屏蔽子類屬性和父類屬性重名時帶來的屬性遮蓋,super. 表示調用父類的方法或屬性
在子類的構造器中若是沒有指定調用父類的哪個構造器,那麼就會調用父類的無參構造器,即super()
注意:
父類的構造器不能被子類繼承
方法和屬性能夠被繼承,權限不限制可否繼承過來,限制的是可否直接訪問
即私有繼承,雖然子類不能直接訪問,但子類依舊擁有。
先構造父類,後構造子類,先this後super
多態:
多態分爲兩種:編譯時多態和運行時多態。
編譯時類型:主觀概念,把它看做什麼。
運行時類型:客觀概念,實際它是什麼。
例:Animal a=new Dog();
指着狗問,這個動物是什麼?
運行時多態的三原則:
對象類型不變。
只能對對象調用編譯時類型中定義的方法。
在程序的運行時,根據對象的運行時類型,找覆蓋後的方法來調用。(運行時動態類型綁定)
強制類型轉換: 必定沒有新對象生成。(父類的引用賦值給子類的引用須要進行強制類型轉換)
關鍵字:instanceof
用法:引用 instanceof 類名 判斷這個引用所指向的對象是否屬於這個類。
用在強制轉換以前,避免類型轉換異常。
if(a instanceof Dog){
Dog d=(Dog)a;
}
多態的做用:把不一樣的子類對象都看成父類來看,能夠屏蔽不一樣子類對象之間的差別,寫出通用的代碼,作出通用的編程,以適應需求的不斷變化。
修飾符static: 把對象相關的變成類相關的,它能夠修飾屬性、方法、代碼塊和內部類
static修飾屬性(類變量):
那麼這個屬性就能夠用" 類名.屬性名 "來訪問,也就是使這個屬性成爲本類的類變量,爲本類對象所共享。
類加載的過程,類自己也是保存在文件中(字節碼文件保存着類的信息)的,java會經過I/O流把類的文件讀入JVM(java虛擬機),這個過程稱爲類的加載。JVM會經過類路徑(CLASSPATH)來找字節碼文件。須要的時候纔會進行類加載,生成對象時是先加載後構造
類變量,會在加載時自動初始化,初始化規則和實例變量相同。
注意:
類中的實例變量是在建立對象時被初始化的
static修飾的屬性,是在類加載時被建立並進行初始化,類加載的過程只進行一次,也就是類變量只會被建立一次。
static修飾方法(靜態方法):
會使這個方法成爲整個類所公有的方法,能夠用" 類名.方法名 "訪問。
static修飾的方法,不能直接訪問本類中的非靜態成員,但本類的非靜態方法能夠訪問本類的靜態成員。
在靜態方法中不能出現this關鍵字。
父類中是靜態方法,子類中不能覆蓋爲非靜態方法,在符合覆蓋規則的前提下,在父子類中,父類中的靜態方法能夠被子類中的靜態方法覆蓋,可是沒有多態。(在使用對象調用靜態方法時實際上是調用編譯時類型的靜態方法)
java中的main方法必須寫成static的緣由:在類加載時沒法建立對象,而靜態方法能夠不經過對象調用,因此在類加載時就能夠經過main方法入口來運行程序。
static修飾初始代碼塊:
這時這個初始代碼塊就叫作靜態初始代碼塊,這個代碼塊只在類加載時被執行一次。
能夠用靜態初始代碼塊初始化一個類。
動態初始代碼塊,寫在類體中的「{}」,這個代碼塊是在生成對象時運行,這種代碼塊叫動態初始代碼塊。Static{ }
單例設計模式:
一個類只容許有一個對象,保證全部引用的對象都是同一個對象。
由於只容許存在一個對象,則不容許在外面直接new出新的對象,因此應該把構造器設爲private,。
在類內定義一個公開的靜態方法,讓使用者進行調用,經過該方法去得到一個實例。
例:
public calss Singleton{
private static Singleton s;
private Singleton(){}
public static Synchroinized Singleton newInstance(){
if ( s == null)
s = new Singleton();
return s;
}
}
修飾符final:不容許改變,能夠修飾變量、方法、類
final修飾變量:
被final修飾的變量就會變成常量,一旦賦值不能改變
常量能夠在初始化時直接賦值,也能夠在構造方法裏賦值,只能在這兩種方法裏二選一,不能不爲常量賦值
常量不會有默認初始值
鎖定棧,使棧中的數據不能夠改變
靜態常量只能在初始化時直接賦值
final修飾方法:
被final修飾的方法將不能被其子類覆蓋,保持方法的穩定不能被覆蓋
final修飾類:
被final修飾的類將不能被繼承
final類中的方法也都是final的
注意:
final不能用來修飾構造方法
訪問權限控制:
private:
本類內部能夠訪問
不能繼承到子類
default:
本類內部能夠訪問,同包其餘類也能夠訪問。
同包可繼承
protected:
本類內部能夠訪問,不一樣包的子類也能夠訪問,同包其餘類也能夠訪問。
能繼承到子類
public:
任何地方均可以訪問
能繼承到子類
修飾符abstract:抽象的,定義框架不去實現,能夠修飾類和方法
abstract修飾類:
會使這個類成爲一個抽象類,這個類將不能生成對象實例,但能夠作爲對象變量聲明的類型,也就是編譯時類型
抽象類就至關於一個類的半成品,須要子類繼承並覆蓋其中的抽象方法,這時子類才又建立實例的能力,若是子類沒有實現父類的抽象方法,那麼子類也要爲抽象類。
abstract修飾方法:
會使這個方法變成抽象方法,也就是隻有聲明而沒有實現,實現部分以";"代替,須要子類繼承實現。
抽象方法表明了某種標準,定義標準,定義功能,在子類中去實現功能(子類繼承了父類並須要給出從父類繼承的抽象方法的實現)。
方法一時間想不到怎麼被實現,或有意要子類去實現而定義某種標準,這個方法能夠被定義爲抽象。
注意:
有抽象方法的類必定是抽象類。可是抽象類中不必定都是抽象方法,也能夠全是具體方法。
接口(interface):
接口的定義:接口從本質上說是一種特殊的抽象類。
關鍵字interface。
在接口中,全部的方法爲公開、抽象的方法:public abstract
在接口中,全部的屬性都是公開、靜態的常量:public static final
接口與接口之間能夠多繼承,用extends,多個之間用逗號隔開。
接口中沒有構造方法,不能用「new 接口名」來實例化一個接口,但能夠聲明一個接口。
接口的實現:
關鍵字implements
一個類實現一個接口必須實現接口中全部的方法,不然其爲抽象類,而且在實現類中的方法要加上public(不能省略)。
類中的默認修飾符:default。
接口中的默認修飾符:public。
一個類除了繼承另外一個類外(只能繼承一個類),還能夠實現多個接口(接口之間用逗號分隔)。
接口的做用:
間接實現多繼承:用接口來實現多繼承並不會增長類關係的複雜度。由於接口不是類,與類不在一個層次上,是在類的基礎上進行再次抽象。
接口能夠抽象出次要類型,分出主、次關係類型,符合看世界的通常方法。
接口隔離,與封裝性有關。一個對象都有多個方面,能夠只展現其中幾個方面,其餘的都隱藏。所以能夠看爲「更高層次的封裝」,把 一個大接口作成若干個小接口。
經過接口制定標準(最重要的做用)----接口的做用,協議的制定。
接口:制定標準。
接口的調用者:使用標準。
接口的實現類:實現標準。
解耦合做用:把使用標準和實現標準分開,使得標準的制定者和實現者解除偶合關係,具備極強的可移植性
例:sun公司提供一套訪問數據庫的接口(標準),java程序員訪問數據庫時針對數據庫接口編程。接口由各個數據庫廠商負責實現。
接口編程的原則
儘可能針對接口編程(能用接口就儘可能用接口)
接口隔離原則(用若干個小接口取代一個大接口)
注意:
接口中沒有構造器,也沒有main方法
封裝類:
Java爲每個簡單數據類型提供了一個封裝類。
除int和char,其他類型首字母大寫即成封裝類。
int Integer
char Character
最經常使用的兩個封裝類Integer和Double
jdk1.4以前基本類型和封裝類的轉化是須要構造器去轉化的,到了jdk1.5是自動進行轉化的
int、Integer和String之間的轉化(最經常使用的)
int i=1;
Integer in = new Integer(i); //int --> Integer
int i = in.intValue(); //Integer --> int
String str = String.valueOf(i); //Int --> String
int ii = Integer.parseInt(str); //String --> int
String s = in.toString(); //Integer --> String
Integer inte = Integer.valueOf(str); //String --> Integer
Object類
hashCode():
返回該對象的哈希碼值
hashCode 的常規協定是:
在 Java 應用程序執行期間,在同一對象上屢次調用 hashCode 方法時,必須一致地返回相同的整數,前提是對象上 equals 比較中所用的信息沒有被修改。
若是根據 equals(Object) 方法,兩個對象是相等的,那麼在兩個對象中的每一個對象上調用 hashCode 方法都必須生成相同的整數結果,反之不必定成立,例如針對hashmap,hashtable,與arraylist是不同的。
toString():
返回該對象的字符串表示。
一般,toString 方法會返回一個「以文本方式表示」此對象的字符串。結果應是一個簡明但易於讀懂。建議全部子類都重寫此方法。
equals()
指示某個其餘對象是否與此對象「相等」。
equals 方法在非空對象引用上實現相等關係:
自反性:對於任何非空引用值 x,x.equals(x) 都應返回 true。
對稱性:對於任何非空引用值 x 和 y,當且僅當 y.equals(x) 返回 true 時,x.equals(y) 才應返回 true。
傳遞性:對於任何非空引用值 x、y 和 z,若是 x.equals(y) 返回 true,而且 y.equals(z) 返回 true,那麼 x.equals(z) 應返回 true。
一致性:對於任何非空引用值 x 和 y,屢次調用 x.equals(y)始終返回 true 或始終返回 false,前提是對象上 equals 比較中所用的信息沒有被修改。對於任何非空引用值 x,x.equals(null) 都應返回 false。
注意:
當此方法被重寫時,一般有必要重寫 hashCode 方法,以維護 hashCode 方法的常規協定,該協定聲明相等對象必須具備相等的哈希碼。
String、StringBuffer和StringBulder
String: 不可改變的Unicode字符序列
池化思想,把須要共享的數據放在池中,用一個存儲區域來存放一些公用資源以減小存儲空間的開銷。
在String類中,以字面值建立時,會到Java方法空間的串池中去查找,若是沒有則會在串池裏建立一個字符串對象,並返回其地址賦給對象變量,若是有就返回串池中字符串的地址,並把這個地址賦給對象變量。
若是是new,則會在堆空間中建立String類的對象,不會有上述的過程
如:
String s1 = "abc"; //新建立,字符串常量池中沒有該串,則會在池中建立一個串"abc"
String s2 = "abc"; //串池中已經存在"abc",則s2會去指向"abc"而不會去建立一個新的
String s3 = new String("abc"); //直接在堆中去開闢一個新的空間,而不會去池中查找
類中的具體方法查看下Api文檔。
調用任何String中的方法,不會改變String自身,除非從新賦值。
StringBuffer: 可改變的Unicode字符序列
容許併發操做,是線程安全的
String類在進行字符串鏈接時會顯得效率很低,就是由於它所產生的對象的屬性是不可以修改的,當鏈接字符串時也就只能建立新的對象。
對於不少字符串鏈接時,應當使用StringBuffer類,使用這個類的對象來進行字符串鏈接時就不會有多餘的中間對象生成,從而優化了效率。
例:對於字符串鏈接String str = "A" + "B" + "C" + "D";
產生:"AB"、"ABC"、"ABCD"
在串池中產生的"AB"、"ABC"明顯是多餘對象,浪費空間。
解決方案:
String s = null;
StringBuffer sb = new StringBuffer("A");
sb.append("B");
sb.append("C");
sb.append("D");
s = sb.toString();
StringBulder: 可改變的Unicode字符序列
操做同StringBuffer,只是不支持併發操做,非線程安全的
集合:保存多個其餘對象的對象,不能保存簡單類型
List:有序(存放元素的順序),可重複的集合
ArrayList:實質就是一個會自動增加的數組
查詢效率比較高,增刪的效率比較低,適用於查詢比較頻繁,增刪動做較少的元素管理的集合。
加載大批量的數據時,先進行手動擴容(就是調用ensureCapacity(int minCapacity)方法),這樣能夠提升效率。
LinkedList:底層是用雙向循環鏈表來實現的
查詢效率低,可是增刪效率很高,適用於增刪動做的比較頻繁,查詢次數較少的元素管理的集合
Set:無序的,不容許有重複元素的集合
HashSet:----注意不是用hash碼的值去存儲
Object類中的hashCode()的方法是全部類都會繼承的方法,這個方法會算出一個Hash碼值返回,HashSet會用Hash碼值去和數組長度取模,對象的模值(這個模值就是對象要存放在數組中的位置,和數組的下標相同)相同時纔會判斷數組中的元素和要加入的對象的內容是否相同,若是不一樣纔會再找位置添加進去,相同則不容許添加。
若是數組中的元素和要加入的對象的hashCode()返回了相同的Hash碼值,纔會用equals()方法來判斷兩個對象的內容是否相同。
注意:要存入HashSet的集合對象中的自定義類必須覆蓋hashCode()、equals()兩個方法,才能保證集合中元素不重複。
TreeSet:可排序的Set
SortedSet接口是Set的子接口,TreeSet是SortedSet接口的實現類,他能夠對集合中的元素進行排序。
將自定義類的對象存放在TreeSet中,這個類須要實現了Comparable接口,TreeSet能夠自動過濾掉重複元素因此不在須要重載hashCode()方法,TreeSet會根據比較規則判斷元素內容是否相同,不一樣則會存入,TreeSet會在元素存入時就進行排序。
Comparable接口:
也叫作可比較接口,這個接口在java.lang包下,只要根據指定類型的排序規則實現了這個接口,就是可排序的。
這個接口中只定義了一個 compareTo(Object o) 方法,該方法的返回值類型是整型,若是當前對象大於參數對象就返回正數,當前對象等於參數對象就返回0,當前對象小於參數對象就返回負值,這樣寫就是升序排列,反之則是進行降序排列。
Comparator接口:
比較器Comparator接口,是另外一種對自定義類型對象的集合總體排序的方法,存在於java.util包下。
這個接口中定義了一個 compare(Object o1,Object o2) 方法來比較兩個對象,這個方法的返回值定義和上面介紹的那個方法是同樣。
利用這種方式,則在建立集合的時候把定義好的比較器做爲參數,構造一個集合
Map:存放key-value對(有關係的兩個對象,一個作key,一個作value,同時存入)
HashMap:基於哈希表的 Map 接口的實現,此實現提供全部可選的映射操做,並容許使用 null 值和 null 鍵
遍歷:
先調用keySet()獲得key的set集合,
再迭代遍歷key的set集合,
根據key獲得value。
Hashtable:同HashMap,通常不使用
HashMap與Hashtable的區別:
HashMap:非線程安全,不支持併發控制,容許空的鍵值對。
Hashtable:是線程安全,支持併發控制,不容許有空的鍵值對。
SortedMap接口:Map的子接口,按某一特定排序規則來存放所加入的鍵值對
實現類:TreeMap類。
Key值的排序規則,同SortedSet接口實現類TreeSet
注意:
key通常是8種基本類型的封裝類或者是String類,拿本身自定義的類做爲Key沒有意義。
key不可重複,value能夠重複
反射:
反射:在運行時動態分析或使用一個類進行工做。
java.lang.Class類:描述類信息的類。
類對象:描述一個類信息的對象,當虛擬機加載類的時候,就會建立這個類的類對象並加載該對象,Class是類對象的類型。
得到類對象的方式:
用" 類名.class "得到這個類的類對象。
用類的對象掉用getClass(),如object.getClass()獲得這個對象的類型的類對象。
可使用Class.forName(類名),也能夠獲得這個類的類對象,(注意,這裏寫的類名必須是全限定名(全名),是包名加類名,XXX.XXX.XXXX)。
基本類型也有類對象,用" 封裝類.TYPE "能夠得到對應的基本類型的類對象。
java.lang.reflect包下的三個重要類:
Field屬性類:用來描述屬性的信息。
Method方法類:方法的信息的描述。
Constructor構造方法類:用來描述構造方法的信息。
Class類中的經常使用方法:
newInstance()
建立此 Class 對象所表示的類的一個新實例(調用無參構造建立的對象)。
getDeclaredMethods()
得到的是一個Method方法類對象的數組,得到本類(不包括父類)聲明的全部(包括private的)方法對象。
getMethods() //推薦使用
得到的是一個Method方法類對象的數組,得到全部(父類的也包括)publice的方法對象。
getDeclaredConstructors()
得到的是一個Constructor構造方法類對象的數組,得到這個類聲明的全部構造方法對象。
getConstructors() //推薦使用
得到的是一個Constructor構造方法類對象的數組,得到全部publice的構造方法對象。
getDeclaredFields() //推薦使用
得到的是一個Field屬性類對象的數組,得到本類聲明的全部屬性的屬性對象。
getFields()
得到的是一個Field屬性類對象的數組,得到全部publice的屬性對象。
使用反射構造一個類的對象的步驟:
a. 得到類對象
b. 得到構造方法對象
c. 得到對象,用構造方法對象調用構造方法,若是使用無參構造方法,能夠跳過第二步,直接使用" 類對象.newInstance() "方法來得到這個類的對象
d. 得到方法對象
e. 用方法對象調用方法(用這個類的對象做爲第一參數)
以下面的例子:
反射機制的實現類:
package day07.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TestReflect {
public static Object get(String className , Map<String,Object> map) throws Exception{
Class c = Class.forName(className); //得到類對象
Object o = c.newInstance(); //得到對象
Set<String> set = map.keySet();
for(String str : set){
String s = "set" + str.substring(0,1).toUpperCase()+str.substring(1);
Field f = c.getDeclaredField(str);
Method m = c.getMethod(s, f.getType()); //得到方法對象
m.invoke(o, map.get(str)); //用方法對象調用方法
}
return o;
}
public static void main(String[] args) throws Exception {
Map m = new HashMap();
m.put("name", "zhang");
m.put("age", 22);
Object o = get("day07.reflect.Student",m);
Student s = (Student) o;
System.out.println(s.getName() + " " + s.getAge());
Map m1 = new HashMap();
m1.put("name", "li");
m1.put("gender", "男");
Object o1 = get("day07.reflect.Teacher",m1);
Teacher t = (Teacher) o1;
System.out.println(t.getName() + " " + t.getGender());
}
}
學生類:
package day07.reflect;
public class Student {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
教師類:
package day07.reflect;
public class Teacher {
private String name;
private String gender;
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
內部類:
定義:
定義在另一個類中的類,就是內部類。
編譯後生成的兩個獨立的類:Outer.class 和Outer$Inner.class。
內部類的分類:
靜態內部類:靜態內部類定義在類中,任何方法外,用static修飾
靜態內部類只能訪問外部類的靜態成員。
在外部類的外部,要建立一個靜態內部類對象不須要外部類對象:
Outer.Inner in = new Outer.Inner();
在本類內部生成內部類對象的方式:
Inner in = new Inner();
成員內部類:做爲外部類的一個成員存在,與外部類的屬性、方法並列
在內部類中能夠直接訪問外部類的私有屬性。
內部類和外部類的實例變量容許命名衝突。
在內部類中訪問實例變量:this.屬性
在內部類訪問外部類的實例變量:外部類名.this.屬性
在外部類的外部,要建立一個成員內部類對象,要首先創建一個外部類對象,而後再建立一個成員內部類對象。
Outer out = new Outer();
Outer.Inner in = out.new Inner();
在本類內部生成內部類對象的方式:
在靜態方法中:Inner in = new Outer().new Inner();
在非靜態方法中:Inner in = this.new Inner();
成員內部類不能夠有靜態成員,這是由於靜態屬性是在加載類的時候建立,這個時候內部類尚未被建立。
局部內部類:在外部類的方法中定義的內部類
與局部變量相似,在局部內部類前不能夠加修飾符public和private,其做用域爲定義它的代碼塊。
局部內部類不只能夠訪問外部類的實例變量,還能夠訪問外部類的局部變量,但要求外部類的局部變量必須爲final的。
配合接口使用,來作到強制弱耦合。
在外部類的外部不可建立局部內部類對象,只能在局部內部類所在的方法中建立:
Inner in = new Inner();
匿名內部類:一種特殊的局部內部類
沒有名字,也沒有class、extends、implements關鍵字
用一種隱含的方式實現一個接口或繼承一個類,而且只能建立一次實例。
實現方式:在某個語句中,new 父類/父接口名字(){ 類體中實現方法 }
例如:
TreesSet ts = new TreeSet(new Comparator(){
public int compare(Object o1, Object o2){
return 0;
}
});
匿名內部類屬於局部內部類,那麼局部內部類的全部限制都對其生效。
匿名內部類是惟一一種無構造方法的類,由於構造器的名字必須合類名相同,而匿名內部類沒有類名。
異常:
異常的分類
Java會將全部的異常封裝成對象,其根本父類爲Throwable。
Throwable有兩個子類:Error 和Exception。
Error:一個Error對象表示一個程序錯誤,指的是底層的低級的不可恢復的嚴重錯誤
遇到Error,程序必定會退出,由於已經失去了運行所必須的物理環境。
對於Error咱們沒法進行處理,由於咱們是經過程序來應對錯誤的,但是程序已經退出了。
Exception:由特定因素,致使程序沒法繼續,但不影響虛擬機的正常執行。
未檢查異常(Runtime Exception):
是由於程序員沒有進行必要的檢查,因爲程序員的疏忽而引發的異常。
對於未檢查異常能夠不處理,編譯能夠經過,應對未檢查異常的方法就是養成良好的檢查習慣
已檢查異常(非Runtime Exception):
是不可避免的,對於已檢查異常必須處理,不然編譯不經過。
異常處理的機制:
當一個方法中有一條語句出現了異常,它就會throw(拋出)一個異常對象(throw 異常對象),而後後面的語句不會執行,而返回上一級方法,其上一級方法接受到了異常對象以後,有可能對這個異常進行處理(進行處理則不會上拋),也可能將這個異常傳到它的上一級,若是最上一級(main方法)不處理就會傳給虛擬機,虛擬機就會終止程序的運行。
異常的處理方式:throws和try-catch方法
try-catch處理方式:
try{ //一個
(1)可能出現異常的語句
} catch(XxxException e /*捕獲的異常*/){ //0或n個
(2)處理異常的代碼
} finally{ //0或1個
(3)必需要執行的代碼
}
(4)方法中的其餘代碼
若是代碼正確,那麼程序不通過catch語句直接向下運行;
若是代碼不正確,則將返回的異常對象和e進行匹配,若是匹配成功,則處理其後面的異常處理代碼。
try中若是發現錯誤,即跳出try塊去匹配catch,那麼try後面的語句就不會被執行。
一個try能夠跟多個catch語句,用於處理不一樣狀況,可是不能將父類型的exception的位置寫在子類型的excepiton以前。
在try-catch後還能夠再跟一子句finally。其中的代碼語句論有沒有異常都會被執行(由於finally子句的這個特性,因此通常將釋放資源,關閉鏈接的語句寫在裏面)。
finally中的代碼和try-catch中的代碼衝突時,finally中的代碼必定會被執行且會忽略try-catch中的代碼。可是若是try-catch中有System.exit(0);(虛擬機退出語句),則不會去執行fianlly中的代碼。另外若是try語句中含有return語句,finally語句在return語句執行後執行。
throws/throw處理方式:
throw 寫在方法內,後面跟一個異常對象。
throws 在方法的定義中說明方法可能拋出的異常,後面跟異常類的名字,聲明這個方法將不處理異常,把異常交給上一級方法處理。
調用時,調用者不能拋出範圍更小的異常。
對於方法a,若是它定義了throws Exception。那麼當它調用的方法b返回異常對象時,方法a並不處理,而將這個異常對象向上一級返回,若是全部的方法均不進行處理,返回到主方法,如主方法也不進行處理,則到虛擬機中,程序停止。
若是在方法的程序中有一行throw new Exception(),那麼其後的程序不執行,若是沒有對這個可能出現的檢查結果進行處理,那麼程序就會報錯。
throws和throw沒有必然的聯繫。
注意:
方法的覆蓋中,若是子類的方法拋出的例外是父類方法拋出的例外的父類型,那麼編譯就會出錯:子類沒法覆蓋父類。
子類拋出的例外或者與父類拋出的例外一致,或者是父類拋出例外的子類型,或者子類型不拋出例外。
若是父類型無throws時,子類型也不容許出現throws。此時只能使用try catch。
自定義異常:
a. 使其繼承Exception或者RuntimeException。
b. 寫構造器,直接調用父類的構造器
斷言(assert):用來調試、測試代碼
格式:
assert 布爾表達式: 字符串 (若是布爾表達式爲false時,這個字符串纔會顯示)
注意:
assert默認是關閉的,使用時須要使用" -ea "進行開啓," -da "是關閉,如:java -ea 類名。
斷言是以異常方式去執行的,當斷言的布爾表達式爲假時,會中斷代碼。
不能繼承性的打開(java -ea:類名 這樣只能打開該類,若是存在父類,不會去打開父類)
圖形界面:
AWT:抽象窗口工具(Abstract Window Toolkit)
組件:圖形界面中全部能看到的,好比按鈕等。
容器:用來管理其餘組件的對象
佈局管理器:佈置組件在容器中的位置和大小
Swing:AWT的一個加強版
構造圖形界面的步驟:
選擇一個容器
設置容器的佈局管理器
向容器中添加組件
事件的監聽
容器(Container):用於管理其餘的組件的對象,組件必須放到容器裏
JFrame:一個最頂層的窗體容器,全部其餘的組件必須放在頂層容器裏。
JPanel:不是頂層容器,必須放在頂層容器中,是透明的(默認)。
容器的方法:
add(Component com) 將組件加入容器。
setLayout(LayoutManager manager) 設置佈局管理器。
setSize(int width,int height) 設置窗口大小
setVisible(boolean b) 顯示或隱藏此組件
setDefaultCloseOperation(int operation) 設置關閉窗體上時默認執行的操做
佈局管理:佈置組件在容器中的位置和大小
FlowLayout:流式佈局管理,Panel和JPanel的默認佈局管理就是FlowLayout
三種構造方式:
FlowLayout()
構造一個新的 FlowLayout,居中對齊,默認的水平和垂直間隙是 5 個單位。
FlowLayout(int align)
構造一個新的 FlowLayout,對齊方式是指定的,默認的水平和垂直間隙是 5 個單位。
FlowLayout(int align, int hgap, int vgap)
建立一個新的流佈局管理器,具備指定的對齊方式以及指定的水平和垂直間隙。
BorderLayout:按方位進行佈局管理,不明確指定,就會默認加載在中間,Frame和JFrame默認的佈局管理器是BorderLayout
兩種構造方式:
BorderLayout()
構造一個組件之間沒有間距的新邊界佈局。
BorderLayout(int hgap, int vgap)
用指定的組件之間的水平間距構造一個邊界佈局。
GridLayout:網格佈局,經過行列、間距來用網格分割,把組件放入網格中,先行後列擺放組件。
三種構造方式:
GridLayout()
建立具備默認值的網格佈局,即每一個組件佔據一行一列。
GridLayout(int rows, int cols)
建立具備指定行數和列數的網格佈局。
GridLayout(int rows, int cols, int hgap, int vgap)
建立具備指定行數和列數的網格佈局,並將水平和垂直間距設置爲指定值。
組件:圖形界面中全部能看到的
JButton :按鈕
JTextField:單行文本域
JTextArea:多行文本區
JLabel:標籤
圖形界面:
佈局管理器:
CardLayout:卡片佈局,面板重疊放置,只能看到一個,最早添加的會被顯示出來,能夠進行翻動
兩種構造方法:
CardLayout()
建立一個間隙大小爲 0 的新卡片佈局。
CardLayout(int hgap, int vgap)
建立一個具備指定的水平和垂直間隙的新卡片佈局。
經常使用的方法:
previous(Container parent)
翻轉到指定容器的前一張卡片。
show(Container parent, String name)
翻轉到已添加到此佈局的具備指定 name 的組件
next(Container parent)
翻轉到指定容器的下一張卡片。
first(Container parent)
翻轉到容器的第一張卡片。
last(Container parent)
翻轉到容器的最後一張卡片。
GridBagLayout:加強版的網格佈局,組件能夠跨行跨列的進行佈局。
構造方法:
GridBagLayout()
建立網格包佈局管理器。
注意:
該佈局管理器的具體實現須要藉助GridBagConstraints類,利用GridBagConstraints類的屬性對組件進行設置,具體內容查看API文檔。
菜單項:
JMenuBar:菜單欄的實現,將JMenu對象添加到菜單欄以構造菜單
構造方法:
JMenuBar()
建立新的菜單欄。
JMenu:菜單的該實現是一個包含JMenuItem的彈出窗口
構造方法:
JMenu(String s)
構造一個新JMenu,用提供的字符串做爲其文本。
JMenuItem:菜單中的項的實現,菜單項本質上是位於列表中的按鈕
構造方法:
JMenuItem(String text)
建立帶有指定文本的JMenuItem。
AWT事件模型:
事件模型的三要素:
事件源(Object):事件的產生者。
事件(EventObject):描述發生了什麼事情。
事件監聽(EventListener):事件的處理者
關係:
事件只與事件源有關,與事件監聽無關
一個事件源能夠註冊多個事件監聽。
一個事件監聽器能夠在多個事件源中註冊。
一個事件源能夠就同一類事件註冊多個事件監聽。
事件處理機制:委派式的處理機制(是一種鬆耦合)
組件自身會產生事件對象,但自己不必定負責處理,而是交給一個監聽者去處理
實現監聽的步驟:
a. 實現監聽接口implements XxxxListener
b. 重寫方法actionPerformed(ActionEvent e)
c. 註冊監聽addXxxxListener(ActionListener l)
適配器:一個重寫了全部接口中方法的類
在java.awt.event包中,會有一些適配器,也就是把相應的XxxxListener,換成XxxxAdapter就是適配器。
在AWT中常常用匿名內部類來繼承適配器作監聽
JFC:java基礎類庫(具體的類能夠查看API文檔)
觀察者模式:
事件監聽者對事件源進行監聽,事件源會發生某些事件,監聽者須要對事件做出相應的處理。
事件監聽者(Observer):
處理事件
事件對象(Observable):
註冊監聽
取消監聽
通知監聽
編程步驟:
a. 定義一個監聽者,使其實現Observer接口,實現其中的方法update(Observable o, Object arg)。
b. 定義一個事件對象,使其繼承Observable類,定義一個產生事件的方法,在方法裏去註冊監聽addObserver(Observer o)、標誌改變setChanged()(若是不寫,則說明該事件沒有發生,監聽者不會反映)、啓動監聽notifyObservers()。
注意:註冊監聽和標誌改變不分前後,但標誌改變和啓動監聽是不能互換的。
應用:當某事物發生變化,須要採起行動,則能夠採用觀察者模式。
適配器模式:
Adapter適配器模式是一種結構型模式,將兩個互不兼容的類糾合在一塊兒。
主要應對:因爲應用環境的變化,經常須要將「一些現存的對象」放在新的環境中應用,可是,新環境要求的接口是現存對象所不知足的。
做用:在不改變源代碼的狀況下實現需求。
java.math.BigDecimal:不可變的、任意精度的有符號十進制數。
必須用String類型進行構造,才能實現精確計算
I/O流後面會詳細講解,今天的瞭解下就能夠了。
多線程:
進程與線程:
進程:同一個操做系統中執行的一個子程序,包含了三部分虛擬CPU、代碼、數據
多進程:同一個操做系統中執行的多個並行的子程序。能夠提升cpu的使用率
線程:在同一個進程當中執行的子程序流
多線程:同一個進程當中併發執行的多個子程序流。能夠提升cpu的使用率
進程與線程的區別:
進程有獨立的進程空間,進程中的數據存放空間(堆空間和棧空間)是獨立的。
線程的堆空間是共享的,棧空間是獨立的,線程消耗的資源也比進程小,相互之間能夠影響的。
java中如何調進程:
調用本地程序的兩個類
Runtime
Runtime.getRuntime.exec(...); //執行一個程序
其返回值就是Process類型
Process
注意:
只有運行狀態的線程纔有機會執行代碼,主線程的停止不會影響其餘的正在運行中的線程,主線程停止也就是main()方法退出了。只有進程中的全部線程都停止時,進程(JVM進程)纔會退出,只要有線程沒有停止,進程就不會退出。
操做系統決定線程是否有優先級,獨佔式的操做系統中系統會有優先級的概念,共享式的操做系統則不會有優先級的。
在線程的內部,程序依然順序執行
線程編程的兩種方法:
寫一個類,繼承Thread類,覆蓋Thread類中繼承來的run()方法,這樣就寫好了自定義的線程類。
繼承java.lang.Thread類:
class MyThread extends Thread{
public void run(){ //覆蓋run(),線程體方法,自身其實就是普通的方法
.......
}
}
啓動線程:
public class TestThread{
public static void main(){
Thread t1=new Mythread();
T1.start(); //調用start()來啓動線程,線程啓動方法,向線程調度器說明當前線程已經準備好了,是一種可運行狀態
}
}
寫一個類,實現Runable接口,實現其中的run()方法。這種方法寫好的類的對象須要做爲線程類建立對象時構造方法的參數。
實現java.lang.Runnable接口:
Class MyThread implements Runnable{
public void run(){
}
}
啓動線程:
public class TestThread{
public static void main(){
Runnable myThread = new MyThread();
Thread t = new Thread(myThread);
t.start();
}
}
Thread中的一些方法:
currentThread()
返回對當前正在執行的線程對象的引用(實現接口方式時使用)
sleep(long millis)
在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行)。
本線程不會去搶,除非sleep結束。
多個線程之間都會去搶執行權限,不會考慮優先級。
yield()
暫停當前正在執行的線程對象,並執行其餘線程。
只給本類或者優先級大於本類優先級的線程去搶。
join()
等待該線程終止。
放在start()前面則沒有用處。
setDaemon(boolean on)
將該線程標記爲守護線程,守護線程須要依賴其餘線程,會在虛擬機中止的時候中止。
線程的生命週期:
1)初始狀態:此時線程只是處於JVM進程中,只是建立了一個線程對象,並無真正開始運行。
2)可動行狀態:調用線程對象的start()方法,此時線程才真正的被建立,進入可運行狀態,等待CPU的調度。「萬事俱備,只欠CPU」。
3)運行狀態:正在運行的線程,此時它擁有CPU的執行權。
4)阻塞狀態:運行狀態中的線程,若是正在等待用戶輸入或調用了sleep()和join()等方法都會致使線程進入阻塞狀態,注意從阻塞狀態出來的線程不必定立刻回到運行狀態,而是從新回到可運行狀態,等待CPU的再次調度。
5)等待隊列狀態:一個線程調用一個對象的wait()會自動放棄該對象的鎖標記,進入等待隊列狀態,只有當有另一線程調用臨界資源的notify()或notifyAll()方法,建議多使用notifyAll(),纔會將等待隊列中的線程釋放,此線程進入鎖池狀態。
6)鎖池狀態:每一個對象都有互斥鎖標記,以防止對臨界資源的訪問形成數據的不一致,和數據的不完整性。一個線程擁有一個對象的鎖標記後,另外一線程想訪問該對象,必須在鎖池中等待。由系統決定哪一個線程拿到鎖標記並運行。注意從鎖池狀態出來的線程不是立刻回到運行狀態,而是從新回到可運行狀態,等待CPU的再次調度。
7)終止狀態:一個線程運行結束後稱爲終止狀態,一個進程中只有全部的線程退出後纔會終止。
多線程:
多線程的同步:
多線程併發訪問同一個對象(臨界資源),若是不對線程進行同步控制,破壞了原子操做(不可再分的操做),則會形成臨界資源(兩個線程同時訪問的資源)的數據不一致。
每個對象都有一個互斥的鎖標記和一個鎖池。當線程擁有這個對象的鎖標記時才能訪問這個資源,沒有鎖標記便進入鎖池,保證在同步代碼塊中只有一個線程,解決了多線程同步控制的問題。
關鍵字:synchronized //線程在同步代碼中必須採用串行訪問
synchronized修飾代碼塊:對括號內的對象object加鎖,只有拿到對象鎖標記的線程才能進入該代碼塊。
public void push(char c){
synchronized(object){ //object只要是對象就能夠,但必須保證是同一對象
……
同步代碼
……
}
}
synchronized修飾方法:在整個方法範圍內對當前對象的加鎖,只有拿到對象鎖標記的線程才能執行該方法。儘量的少用
public synchronized void push(char c) {
……
同步代碼
……
}
一個線程能夠同時擁有多個對象的鎖標記,鎖標記若是過多,就會出現線程等待其餘線程釋放鎖標記,而又都不釋放本身的鎖標記供其餘線程運行的情況,形成死鎖。
靜態方法能夠是同步方法:可是它所鎖的並非當前對象,是類對象。
抽象方法不能是synchronized同步的方法。
構造方法不能是synchronized同步的方法。
線程由於未拿到鎖標記而發生阻塞進入鎖池(lock pool)。每一個對象都有本身的一個鎖池的空間,用於放置等待運行的線程。由系統決定哪一個線程拿到鎖標記並運行
利用Collections類中的synchronizedXxxx(Xxxx ss)方法能夠獲得相應集合的線程安全的集合
注意:
在同步語句塊中不能直接操做對象鎖正在使用的對象。
對象與鎖一一對應。
同步依賴對象鎖,鎖對象相同,同步語句串行,鎖對象不一樣,同步語句並行。
順序鎖,不要回調,反向打開。
能不用同步就不用同步,有數據共享衝突時才使用同步。
等待通知機制:
線程間通訊使用的空間稱之爲對象的等待對列(wait pool),該隊列也是屬於對象的空間的。
使用Object類中wait()的方法,在運行狀態中,線程調用wait(),此時表示線程將釋放本身全部的鎖標記和CPU的佔用,同時進入這個對象的等待池。等待池的狀態也是阻塞狀態,只不過線程釋放本身的鎖標記。只有在對該對象加鎖的同步代碼塊裏,才能掉用該對象的wait(),表示線程將會釋放全部鎖標記,進入等待隊列,線程將進入等待隊列狀態。
一個線程進入了一個對對象加鎖的同步代碼塊,並對該對象調用了wait()方法,釋放本身擁有的全部鎖標記,進入該對象等待隊列,另外一個線程得到了該對象的鎖標記,進入代碼塊對該對象調用了notify()方法,就會從等待隊列裏釋放出一線程,釋放出的這個線程要繼續運行就還要進入那個同步代碼塊,由於得不到要訪問代碼塊對象的鎖標記,而進入該對象的鎖池,等待鎖標記釋放。
什麼狀況下釋放鎖:
同類代碼執行完畢。
異常未處理,錯誤退出。
調用wait()。
相關方法:
1) wait():交出鎖和CPU的佔用;
2) notify():將從對象的等待池中移走一個任意的線程,並放到鎖池中,那裏的對象一直在等待,直到能夠得到對象的鎖標記。
3) notifyAll(): 將從等待池中移走全部等待那個對象的線程並放到鎖池中,只有鎖池中的線程能獲取對象的鎖標記,鎖標記容許線程從上次因調用wait()而中斷的地方開始繼續運行
注意:
用notifyAll()取代notify(),由於在調用notify()方法時,是由系統決定釋放出哪一個線程。
只能對加鎖的資源進行wait()和notify()。
判斷是否進行等待wait()時,用while代替if來進行判斷。
I/O流
字節輸入流:InputStream類爲全部字節輸入流的父類
三個基本的read()方法:
int read()
從流裏讀出的一個字節。不推薦使用
int read(byte[] b)
將數據讀入到字節數組中,並返回所讀的字節數
int read(byte[] b, int off, int len)
off 從哪裏開始讀。
len 讀取多少。
將輸入流中最多 len 個數據字節讀入字節數組。
其它方法:
void close()
關閉此輸入流並釋放與該流關聯的全部系統資源。
int available()
返回不受阻塞地今後輸入流讀取的字節數。
long skip(long n)
跳過和放棄此輸入流中的n個數據字節,該方法有可能失效。
boolean markSupported()
測試此輸入流是否支持 mark 和 reset 方法。
void mark(int n)
在此輸入流中標記當前的位置
void reset()
將此流從新定位到對此輸入流最後調用 mark 方法時的位置。
字節輸出流:OutputStream類是全部字節輸入流的父類
三個基本的write()方法:
void write(int n)
將指定的字節寫入此輸出流。
void write(byte[] b)
將 b.length 個字節從指定的字節數組寫入此輸出流。
void write(byte[] b, int off, int len)
將指定字節數組中從偏移量off開始的len個字節寫入此輸出流。
其它方法:
void close()
關閉此輸出流並釋放與此流有關的全部系統資源。
void flush()
刷新此輸出流並強制寫出全部緩衝的輸出字節。
文件輸入輸出流:FileInputStream和FileOutputStream
要構造一個FileInputStream,所關聯的文件必須存在並且是可讀的。
如:
FileInputStream fis = new FileInputStream("myfile.dat");
要構造一個FileOutputStream,而輸出文件已經存在,則它將被覆蓋。
如:
FIleOutputStream fos = new FileOutputStream("results.dat");
要想以追加的方式寫,則須要一個額外的參數,如:
FileOutputStream outfile = new FileOutputStream("results.dat" ,true); //參數爲true時輸出爲追加,爲false時爲覆蓋。
I/O流
流的概念:程序與數據來源之間的橋樑
流的分類:
按數據方向分:輸入流和輸出流
輸入流:InputStream/Reader
輸出流:OutputStream/Writer
按數據類型分:字節流和字符流
字節流:InputStream/OutputStream
字符流:Reader/Writer
按流的功能分:節點流和處理流
節點流用操做數據的來源。
處理流用來封裝節點流,從而給節點流增長一個功能,不能獨立存在,在關閉流時若是使用了處理流,只需關閉最外層的流就能夠了。
區分節點流和處理流的小方法:
看構造器,節點流參數爲數據來源,而處理流參數爲其餘流。
選擇流的思路:
先考慮是輸入流仍是輸出流,
再考慮是字節流仍是字符流,
最後考慮是節點流仍是處理流。
字符流:Reader和Writer全部字符流的父類型
Java技術使用Unicode來表示字符串和字符,並且提供16位版本的流,以便用相似的方法處理字符。
若是構造了一個鏈接到流的Reader和Writer,轉換規則會在使用缺省平臺所定義的字節編碼和Unicode之間切換。
橋樑流:InputStreamReader和OutputStreamWriter(字節流轉化成字符流的橋轉換器)
這兩個類不是用於直接輸入輸出的,他是將字節流轉換成字符流的橋轉換器,並能夠指定編解碼方式。
逐行讀寫流:BufferedReader/BufferedWriter
以上兩個都是過濾流,須要用其餘的節點流來做參數構造對象。
BufferedReader的方法:readLine():String ,當他的返回值是null時,就表示讀取完畢了。要注意,再寫入時要注意寫換行符,不然會出現阻塞。
BufferedWriter的方法:newLine() ,這個方法會寫出一個換行符。
管道流:線程交互的時候使用
PipedInputStream/PipedOutputStream
傳送輸出流能夠鏈接到傳送輸入流,以建立通訊管道。傳送輸出流是管道的發送端。一般,數據由某個線程寫入 PipedOutputStream 對象,並由其餘線程從鏈接的 PipedInputStream 讀取。
注意:管道輸出流和管道輸入流須要對接。
數據流:DataInputStream和DataOutputStream
經過流來讀寫Java基本類,注意DataInputStream和DataOutputStream的方法是成對的。
支持直接輸出輸入各類數據類型。
注意:使用DataOutputStream/DataInputStream時,要注意寫入順序和讀取順序相同,不然會將沒有分割寫入的信息分割不正確而讀取出錯誤的數據。
Properties類:針對屬性文件(*.properties,內容是name=value)進行操做,在java.util包下
load(InputStream inStream)
從輸入流中讀取屬性列表(鍵和元素對)。
getProperty(String key)
用指定的鍵在此屬性列表中搜索屬性。
java編碼方式:
編碼:把字符轉換成數字存儲到計算機中,按ASCII將字母映射爲整數。
解碼:把數字從計算機轉換成相應的字符的過程。
不一樣的國家有不一樣的編碼,當編碼方式和解碼方式不統一時,產生亂碼。
由於美國最先發展軟件,因此每種的編碼都向上兼容ASCII 因此英文沒有亂碼。
ASCII(英文) 1個字符佔一個字節(全部的編碼集都兼容ASCII)
ISO8859-1(拉丁文) 1個字符佔一個字節
GB-2312/GBK 1個字符佔兩個字節(多用於中文)
Unicode 1個字符佔兩個字節(網絡傳輸速度慢)
UTF-8 變長字節,對於英文一個字節,對於漢字兩個或三個字節。
中文編碼時出現亂碼的狀況:
用流操做文件。
網頁(動態靜態)。
網絡傳遞消息。
解決亂碼的方式:
String temp = 亂碼的字符串
temp = new String(temp.getBytes("ISO8859-1") , "GBK")
將temp按照ISO8859-1的方式進行解碼生成一個字節序列,而後在按照GBK的方式解碼字節序列生成字符串。
File類:可表示文件或者目錄
File下的方法是對磁盤上的文件進行磁盤操做,可是沒法讀寫文件的內容。
構造器:
File(String pathname) //以文件的路徑作參數
File類的方法:
boolean createNewFile()
建立一個新文件
File createTempFile(String prefix, String suffix, File directory)
在指定目錄中建立一個新的空文件,使用給定的前綴和後綴字符串生成其名稱。會在前綴和後綴之間加一個隨機數
boolean mkdir()
建立一個新目錄
boolean delete()
刪除文件,刪除的是建立File對象時指定與之關聯建立的那個文件。
String[] List()
返回當前File對象下全部顯文件和目錄名(相對路徑)
File[] ListFiles()
返回當前File對象(必須是目錄)下的全部File對象,能夠用getName()來訪問到文件名。
boolean isDirectory()和boolean isFile()
判斷到底是目錄仍是文件。
boolean exists()
判斷文件或文件夾是否存在。
String getPath()
得到相對路徑。
String getAbsolutePath()
得到文件的絕對路徑
注意:
File類的對象實施表示一個文件並非真正的文件,只是一個代理而已,經過這個代理來操做文件
建立一個文件對象和建立一個文件在java中是兩個不一樣的概念。前者是在虛擬機中建立了一個文件,但卻並無將它真正地建立到OS的文件系統中,隨着虛擬機的關閉,這個建立的對象也就消失了。而建立一個文件纔是在系統中真正地創建一個文件。
例如:
File f=new File(「11.txt」); //建立一個名爲11.txt的文件對象
f.CreateNewFile(); //真正地建立文件
RandomAccessFile:
容許隨機訪問文件,類支持直接輸出輸入各類數據類型。
構造器:
RandomAccessFile(File file, String mode)
建立從中讀取和向其中寫入(可選)的隨機存取文件流,該文件由 File 參數指定。
RandomAccessFile(String name, String mode)
建立從中讀取和向其中寫入(可選)的隨機存取文件流,該文件具備指定名稱。
mode( r:以只讀方式打開 rw:可讀可寫,不存在則建立)
相關方法:
long getFilePointer()
返回文件指針的當前位置。
void seek(long pos)
設置文件指針到給定的絕對位置。
long length()
返回文件的長度。
對象流:ObjectInputStream和ObjectOutputStream(實現對象序列化)
對象流是過濾流,須要節點流做參數來構造對象,用於直接把對象寫入文件和從文件中讀取對象。
只有實現了Serializable接口的類型的對象才能夠被讀寫,Serializable接口是個標記接口,其中沒有定義方法。
對象會序列化成一個二進制代碼,文件中保存對象的屬性。
writeObject(o)、readObject()這兩個是對象讀寫操做時用的方法。
Object o = new Object();
FileOutputStream fos=new FileOutputStream("Object.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(o);
oos.close();
FileInputStream fis =new FileInputStream(「Object.txt」);
ObjectInputStream ois =new ObjectInputStream(fis);
Object o = (Object)Ois.readObject();
ois.close();
一個類中有其餘類型的對象,那麼,這個類實現了Serializable接口,在對象序列化時,也一樣要求這個類中屬性都可以對象序列化(基本類型除外)。
注意:
對於對象流的操做,在寫對象時要一次寫入完畢,若是使用追加模式寫入,只會讀取到上一次寫入的對象,使用對象流寫入時,會先寫入一個頭部,而後寫入數據,最後加上結束符號,若是使用追加方式寫入的話,那就會在結束符號繼續向下寫入,可是在讀取時只會讀到結束符爲止,之後再次寫入的數據就會丟失。
包名、類名和屬性能夠被序列化,方法和構造器不會被序列化的。
靜態屬性不會被序列化的。
屬性會被遞歸序列化的,也就是一個類中有引用類型的屬性,若是這個屬性對應的類實現了Serializable接口,在對象序列化時,也一樣會對這個類中的屬性進行對象序列化,若是沒有實現Serializable接口,則會拋出異常。
全部屬性必須都是可序列化的,特別是當有些屬性自己也是對象的時候,要尤爲注意這一點。
網絡中傳遞對象必須實現序列化。
nio無阻塞的I/O(優化的I/O)
java.nio 定義塊
Buffer類:一種用於特定的基本類型數據的容器
緩衝:就是塊,用來存儲內容。
容量:內存開闢的大小,根據類型的不一樣,有不一樣的空間。
界限:可用部分,即不該讀取或寫入的第一個元素的索引。
位置:當前指針的位置,從0開始。
容量>=界限>=位置
相關方法:
int capacity()
返回此緩衝區的容量。
int limit()
返回此緩衝區的界限。
int position()
返回此緩衝區的位置。
Buffer flip()
至關於截斷沒有用的空間,而後把指針移向開頭,使limit=position,position=0
Buffer position(int newPosition)
設置此緩衝區的位置。
當有大的文件須要處理的時候,爲了避免影響性能建議用直接緩衝。
Buffer有直接緩衝和間接緩衝兩種。
只有ByteBuffer類提供了直接緩衝。使用直接緩衝,不影響程序。其它類想用直接緩衝須要進行轉換。
java.nio.channels 對塊進行讀寫的通道,相似於之前的流
Channel接口:用於 I/O 操做的鏈接
編程步驟:
a. 先建立一個I/O流,
b. 使用I/O流.getChannel()方法,得到通道,
c. 建立大小合適的ByteBUffer,
d. 通道的對象.read(buffer)/write(buffer)進行讀寫,
e. 關閉全部的流和通道,
f. 若是有多線程併發,可使用"通道.lock()"得到FileLock對象,用FileLock.release() 釋放此鎖定。
g. 當遇到編碼問題,使用CharSet、CharsetDecoder、CharsetEncoder三個類去解決
注意:
在讀以前須要調用一下clear()方法,幫助讀操做清理緩衝;寫以前須要調用flip()方法,幫助寫操做清理緩衝。
java.nio.charset 字符集,進行編碼解碼
Charset類:編碼類,編碼的信息
forName(String charsetName)
生成一個CharSet實例。
decode(ByteBuffer bb)
將此 charset 中的字節解碼成 Unicode 字符的便捷方法。
encode(CharBuffer cb)
將此 charset 中的 Unicode 字符編碼成字節的便捷方法。
CharsetDecoder類:解碼器
可以把特定 charset 中的字節序列轉換成 16 位 Unicode 字符序列的引擎。
CharsetEncoder類:編碼器,編碼的行爲
可以把 16 位 Unicode 字符序列轉換成特定 charset 中字節序列的引擎。
網絡編程:
網絡基礎知識
Mac地址:每一個網卡專用地址,也是惟一的。
端口(port):應用程序(進程)的標識(網絡通訊程序)
OS中能夠有65536(2^16)個端口,進程經過端口交換數據。
端口是一種抽象的軟件結構,與協議相關:TCP的23端口和UDT的23端口爲兩個不一樣的概念。
端口應該用1024以上的端口,如下的端口都已經設定功能。
協議:爲了進行網絡中的數據交換而創建的約定,協議是爲了保證通訊的安全,不一樣層的協議是徹底不一樣的。
TCP協議:傳輸層的協議,重發一切錯誤的信息
IP協議:保證地址和主機一一對應(ip地址+網卡地址)
TCP編程:
TCP是一種面向鏈接的保證可靠傳輸的協議。經過TCP協議傳輸,獲得的是一個順序的無差錯的數據流。發送方和接收方的成對的兩個socket之間必須創建鏈接,以便在TCP協議的基礎上進行通訊,當一個socket(一般都是server socket)等待創建鏈接時,另外一個socket能夠要求進行鏈接,一旦這兩個socket鏈接起來,它們就能夠進行雙向數據傳輸,雙方均可以進行發送或接收操做。
1) 服務器分配一個端口號,服務器使用accept()方法等待客戶端的信號,信號一到打開socket鏈接,從socket中取得OutputStream和InputStream。
2) 客戶端提供主機地址和端口號使用socket端口創建鏈接,獲得OutputStream和InputStream。
Server端編碼的步驟:
一、new ServerSocket 打開端口
二、調ServerSocket的accept()等待客戶鏈接,當鏈接成功返回交互的Socket。
三、調用Socket.getInputStream,getOutputStream得到服務器端的IO流
四、用處理流封裝後與客戶端交互,記住你讀我寫,一讀一寫。
五、關閉單一客戶端調用Socket的close(),關閉服務器調ServerSocket的close();
Socket端編碼步驟:
一、new Socket(Server ip,Server port)試圖鏈接,如成功纔有對象
二、調用Socket.getInputStream,getOutputStream得到服務器端的IO流
三、用處理流封裝後與客戶端交互,記住你讀我寫,一讀一寫。
四、關閉,只有Socket的close()方法。
網絡編程:
多線程+網絡:
一、服務器端的等待客戶鏈接代碼( while(true) ),服務器端與單個客戶端交互的代碼放入線程體( run )
二、客戶端若有其餘要求,與服務器交互的代碼也要放入線程體
三、ServerSocket和Socket編碼基於TCP/IP協議,重發一切錯誤數據,當網絡很差時會使性能不好
四、Server端
new ServerSocket啓動等待鏈接線程
在accept後啓動交互線程
注意:交互時注意對應產生,讀寫流對應和次數對應
URL:網址,統一資源定位器
經常使用的構造器:
URL(String spec)
spec 一個完整的網址(協議+網址)
根據 String 表示形式建立 URL 對象。
URLConnection:與網址進行鏈接
經過URL的openConnection()方法生成一個URLConnection實例,經過下面兩個方法,進行流的操做
getInputStream()
返回今後打開的鏈接讀取的輸入流
getOutputStream()
返回寫入到此鏈接的輸出流。
UDP編程:這種信息傳輸方式至關於傳真,信息打包,在接收端準備紙
特色:
一、一種無鏈接協議,速度快
二、不保證數據的完整,不會進行重發
DatagramSocket和DatagramPacket類:
DatagramSocket:此類表示用來發送和接收數據報包的套接字。
DatagramPacket:數據報包,是UDP下進行傳輸數據的單位,數據存放在字節數組中,其中包括了目標地址和端口以及傳送的信息。
用於接收:
DatagramPacket(byte[] buf , int length)
用於發送:
DatagramPacket(byte[] buf , int length , InetAddress address , int port )
UDP發送端:
一、建立一個DatagramSocket,不須要參數
二、建立一個DatagramPacket,指明接收方的IP地址和端口號
三、發送數據send(DatagramPacket p)
四、關閉DatagramSocket
UDP接收端:
一、建立一個DatagramSocket,指定接收方的IP地址和端口號
二、建立一個DatagramPacket,不須要IP地址和端口號
三、接收數據receive(DatagramPacket p)
四、關閉DatagramSocket
經常使用類庫:
java.lang.*:
System 系統
Object 對象
clone()
equals()
hashCode()
toString()
Class 類
String/StringBuffer/StringBuilder 與字符串相關的
Thread 線程
全部的封裝類
java.util.*:
Set--->HashSet,TreeSet
List--->ArrayList
Map--->HashMap(線程安全,不支持空),HashTable(線程不安全,支持空)
Collections--->外同步
Properties
Date
觀察者-->Observable,接口Observer
數據結構+工具類
java.sql.*: 後面立刻會講到,JDBC
java.awt/swing.*:沒什麼機會用到
java.io.*: 流至關的多
File/FilenameFilter
Serializable 對象序列化接口
注意:寫一個類要考慮的事情:一、無參構造器,二、實現序列化接口,三、重寫equals,hashCode
FileInputStream
FileOutputStream
InputStreamReader
PrintStream
BufferedReader
nio包
java.net.*: 之後JSP,Servlet用的時候這個包都已經寫好了
InetAddress--->IP地址
URL----------->網址
URLConnection---->鏈接
ServerSocket,Socket----TCP/IP
DatagramSocket,DatagramPacket----UDP
一些零散的類:
Comparable(可比較的),Comparator(比較器)
java.math.*;數字在商業軟件中應用時找這個包
BigDecimal
與反射相關的:java.lang.reflect: 用的機會比較少
Runtime(運行環境),Process(進程) ,這兩個在java.lang包裏,用了這些就不能跨平臺了,並且效率低
國際化:讓世界上每一個人都能看懂。
Locale類(java.util包下):包括全部國家、地區、語言
存在不少的靜態屬性,來表示國家、語言
三種構造方法:
Locale(String language)
根據語言代碼構造一個語言環境。
Locale(String language, String country)
根據語言和國家構造一個語言環境。
Locale(String language, String country, String variant)
根據語言、國家和變量構造一個語言環境。
經常使用方法:
Locale getDefault()
得到此 Java 虛擬機實例的當前默認語言環境值。
String getDisplayCountry()
返回適合向用戶顯示的語言環境國家名。
void setDefault(Locale newLocale)
爲此 Java 虛擬機實例設置默認語言環境。
String getLanguage()
返回此語言環境的語言代碼。
String getCountry()
返回此語言環境的國家/地區代碼。
注意:
國家會兼容語言,但語言不會兼容國家。
java.text.*:該包下存在許多格式化類
NumberFormat抽象類:
經常使用方法:
NumberFormat getInstance()
返回當前默認語言環境的通用數字格式。
NumberFormat getInstance(Locale inLocale)
返回指定語言環境的通用數字格式。
String format(double number)
根據國家,進行格式規範。
NumberFormat getCurrencyInstance(Locale inLocale)
返回指定語言環境的貨幣格式。
SimpleDateFormat類:
模式字母:
y 年
M 年中的月份
H 一天中的小時數(0-23)
h am/pm 中的小時數(1-12)
m 小時中的分鐘數
s 分鐘中的秒數
構造器:
SimpleDateFormat(String pattern)
用給定的模式和默認語言環境的日期格式符號構造 SimpleDateFormat。
經常使用方法:
String format(Date date)
將一個 Date 格式化爲日期/時間字符串。
注意:
看到相應的模式字母,就會進行轉換。
實現國際化:
一、先寫各個語言對應的文字類,使其extends ListResourceBundle,而後重寫getContents(),返回一個二維數組。
二、在程序中按照Local和ListResourceBundle的baseName來選擇對應的資源,調用getString()/getObject()取得value
ResourceBundle類:
ResourceBundle getBundle(String baseName, Locale locale)
baseName爲對應的ListResourceBundle的類名(包名.類名)
使用指定的基本名稱和語言環境,以及調用方的類加載器獲取資源包。
注意:根據key去查找value時,當前沒有會去查找默認的,默認的也沒有則會拋出異常
5.0新特性:
一、自動裝箱,自動解箱(簡單類型->對象類型)
小於127的數值在自動裝箱時只作一次裝箱,作" == "時相等。
null沒法自動解箱。
先裝箱後賦值和先解箱後賦值時,須要注意是否可以匹配。
二、靜態import
用於導入類中的靜態屬性和靜態方法。
格式:import static 包名.類名.屬性/方法/*
注意:
必須是靜態的成員。
靜態導入時,不容許導入同名方法/屬性。
使用時,可省略" 類名. "就像使用本類方法同樣
三、加強for循環:for( : )
方式統一,能夠處理數組和集合。
不能夠同時對兩個以上的集合進行操做。
不支持刪除元素。
四、可變長的參數:(...)
用於取代數組,實際上仍是按數組進行處理,容許傳遞非數組的值(0到n個,中間用逗號分隔)。
可變長參數只能出現一次,且必定會放在參數列表的最後。
做參數時,可變長參數能夠不傳,但數組不能夠。
五、格式化輸入輸出:Scanner類
瞭解下就能夠,知道有這個類就OK。
六、枚舉Enum:本質上也是一個類,具備類全部特性
格式:
enum 枚舉名{
枚舉值1,
枚舉值2,
.....
}
特性:
顯示一些同類型的清單。
一個枚舉值就是一個枚舉對象。
能夠有構造器,但不能是public的。
具備一個私有的默認無參的構造器,顯式構造後,默認的構造器會消失。
屬性,方法和類同樣。
枚舉是final的(對於外部沒法繼承),但在內部能夠去實現。
注意:
清單裏的類,會調用匹配的構造器,如無,則會報錯。
在枚舉中能夠有抽象方法,但在清單中的全部子類都必須實現他。
若是要寫屬性和方法,則最後的一個枚舉值要以分號結束。
枚舉中的values()方法會返回枚舉中的全部枚舉值: Color[] ss = Color.values();
七、泛型
八、元數據(註釋),項目中推廣度通常
5.0新特性:
泛型:
泛型的形式:
<E>
<E extends 類型>
<E extends Numner&comparator> 類名&接口,表示E繼承Numner類實現comparator接口
<?> 泛型通配符表示任意類型,僅用於傳參
<? extends 類型> 表示這個類型能夠是該類或者該類的子類。
<? super 類型> 表示這個類型能夠是該類或者該類的父類。
泛型的優勢:
指定泛型後,取出數據時不須要進行強制類型轉換,能夠直接賦值給相應類型。
能夠限定集合中的元素類型,保證集合中的元素是按照要求放入的。
能夠加強多態(繼承多個接口而無需寫繼承類)。
保證參數有效。
泛型的侷限性:
不能實例化泛型
T t = new T(); //error
數組不可用泛型限定
List<String>[] list = new List<String>[10]; //錯誤
E[] a = new E[10]; //錯誤
類的靜態變量不能聲明爲類的泛型類型
public class GenClass<T> {
private static T t; //編譯錯誤
}
靜態方法能夠是泛型方法(在修飾符和返回值之間寫泛型),可是不可使用類的泛型。
static void copyArrayToList(Object[] os,List<T> ls){
//錯誤,T爲類的泛型
}
static <E> void copyArrayToList(E[] os,List<E> ls){
//泛型方法,正確的
}
泛型不能使用簡單類型
GenList<int> nList = new GenList<int>(); //編譯錯誤
泛型類不能是異常類,也就是該泛型類不能繼承自Throwable以及其子類
public class MyExpection<T> extends Exception{ } //編譯錯誤
能夠拋出(throws)泛型類,但catch的參數不能是泛型類。
注意:
編譯時類型的泛型和運行時類型的泛型必定要一致,沒有多態。
支持泛型的集合,只能存放指定的類型,或者是指定類型的子類型。
註釋(元數據):
描述代碼的代碼,做用是規範編譯器的語法。
三種內置註釋:
@Deprecated 所標註的程序元素是不推薦使用的
@Override 檢查是否爲合法的覆蓋父類的方法
@SuppressWarnings 註釋類或方法,忽略其中的某些類型的警告信息
註釋的三種類型:
標記註釋:不須要任何參數
@Override
@Deprecated
單值註釋:有一個值的註釋
@註釋名(值名=值)
值名通常爲value,能夠省略的,直接寫值就能夠
值的類型是有限制的,只能是如下幾種:
8種基本數據類型
String
Class
Enum
Annotation
以及他們的數組
多值註釋:每一個值之間用逗號隔開
四種元註釋:java.lang.annotation中的類
元註釋:註釋註釋的註釋,用來限定註釋的特徵
@Terget 用來限定某個註釋的使用範圍,能夠對什麼元素進行註釋
@Retention 用來描述註釋的有效範圍
@Inherited 用來描述某註釋是否有繼承性
@Documented 用來限定註釋的信息是否可以進行文檔化
自定義註釋:
在自定義註釋時,要用元註釋來進行描述。
如:
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InProgress {
String author(); //定義屬性
String limited();
}
解析註釋:利用反射
一、Class.forName()
二、getMethod
三、判斷是否有註釋
四、getAnnotation
併發線程:
三個多線程包:
java.util.concurrent 包含了經常使用的多線程工具,是新的多線程工具的主體。
java.util.concurrent.atomic 包含了不用加鎖狀況下就能改變值的原子變量。
java.util.concurrent.locks 包含鎖定的工具。
Executor接口:
替代了Thread類,他能夠建立定量的、動態的以及週期性的線程池。
ExecutorService接口:
線程池,用來存放線程來節省建立和銷燬資源的消耗。
Callable和Future接口:
Callable是相似於Runnable的接口,實現Callable接口的類和實現Runnable的類都是可被其它線程執行的任務。Callable和Runnable有幾點不一樣:
Callable規定的方法是call(),而Runnable規定的方法是run().
Callable的任務執行後可返回值,而Runnable的任務是不能返回值的。
call()方法可拋出異常,而run()方法是不能拋出異常的。
運行Callable任務可拿到一個Future對象,經過Future對象可瞭解任務執行狀況,可取消任務的執行,還可獲取任務執行的結果。
軟件開發流程:
一、可行性分析
二、需求分析->開發測試
三、概要設計->分隔模塊,定義框架等
四、詳細設計->類設計、接口設計
五、編碼
六、測試
七、部署
八、維護
單元測試:
要求:
要有邊界值的分析,主要針對分支語句的臨界點
語句覆蓋,保證寫的任何語句都要運行到
斷定覆蓋,全部判斷的地方都要覆蓋掉
條件覆蓋,保證全部條件都要覆蓋掉
路徑覆蓋,全部分支都要測試到
步驟:
一、針對每一個類寫一個TestCase,在setUp方法中初始化要測試類,在tearDown方法中將測試類置爲null
二、逐一編寫以test開頭的方法
三、新建一個套件類,再把全部的TestCase類加入套件類
Ant:用於對項目的總體構建、修改及部署等操做
Ant的下載:
去阿帕奇官方網站下載
在eclipse的eclipse3.2\plugins\org.apache.ant_1.6.5
創建ant的步驟:
一、寫類:src和build.xml必須本身寫,src中的源程序要按照包結構去構建好
projectName
classes
src
build.xml
二、寫build.xml
<?xml version="1.0" encoding="GB2312" ?>
<!-- 一個項目,可包含不少任務組(target) -->
<project default="main" basedir=".">
<!--屬性部分,能夠寫相似全局變量-->
<property name="src" value="src\test" />
<!-- 項目中的一個任務組,可包含不少任務(task:javac,java...) -->
<target name="main" description="begin build">
<!--建立目錄-->
<mkdir dir="classes" />
<!--編譯-->
<javac srcdir="${src};src" destdir=".\classes"/>
<!--運行-->
<java classname="test.Test">
<classpath>
<pathelement path=".\classes"/>
</classpath>
</java>
</target>
<!--清除全部class-->
<target name="clean" description="begin clean">
<delete dir="classes" />
</target>
<!--從新創建項目-->
<target name="all" depends="clean,main" description="begin all">
</target>
</project>
三、ant配置環境變量
Path->org.apache.ant_1.6.5\bin
ClassPath->org.apache.ant_1.6.5\lib
四、運行
建立可運行的jar文件:
一、先建起一個空文件夾
二、把全部的源文件拷貝到該文件夾下
三、javac -d . * 編譯此文件夾下各源文件
四、刪除源文件
五、jar -cvf test.jar * 完成第一次打包
六、jar -xvf test.jar 解壓
七、刪除test.jar
八、改META_INF中的文件,加上Main-Class: MenuFrame (注意中間有空格),保存
九、jar -cvfM test.jar *
十、java -jar test.jar 能夠運行
重構:
在不改變軟件任何功能的前提下對代碼進行修改,調整其結構,提升其可讀性,下降其修改的成本。
重構的基本思想就是集中精力使設計簡化,而且在新的需求出現時提供一個持續發展(而非擴展)的環境。
重構是一項功能強大的技術,但需以微小的步伐修改程序才行。
重構的優勢:
重構能夠改進軟件的設計;
重構可使你的代碼看起來更易理解;
重構能夠找出潛伏的Bug;
重構能夠幫助你提升編程的速度――在一次次的迭代過程當中阻止系統腐敗變質,減小在調試中所花的時間;
重構可使咱們更快速的開發軟件,甚至還能夠提升咱們的設計質量。
利用eclipse重構代碼:
代碼封裝
方法移位(父類<->子類)
抽取方法
提煉接口