一、數(shù)組
public class Main {
public static void main(String [] args){
//在棧中創(chuàng)建應(yīng)用數(shù)組和對(duì)象變量
int [] x;
//在堆中開(kāi)辟一塊內(nèi)存存放數(shù)組的位置
x=new int[100];
//將引用變量設(shè)置為null 堆中數(shù)據(jù)將無(wú)法得到引用,會(huì)啟動(dòng)Java中的垃圾回收機(jī)制從堆中清除出去,再次引用會(huì)出現(xiàn)空指針異常
x=null;
//靜態(tài)數(shù)組不能直接定義數(shù)組的長(zhǎng)度
int []y=new int[]{7,5,6};
//使用System.arraycopy()函數(shù)拷貝數(shù)組
//用Arrays.sort來(lái)排序數(shù)組
Arrays.sort(y);
//獲取數(shù)組的長(zhǎng)度
for(int i=0;i<y.length;i++){
System.out.println("y["+i+"]="+y[i]);
}
//局部變量不會(huì)自動(dòng)初始化
//在棧中的局部變量y沒(méi)有指向堆中的對(duì)象
int [] z=new int[10];
//將x中的元素,從下標(biāo)0開(kāi)始,拷貝到y(tǒng)中,從下標(biāo)0拷貝,一共3個(gè)
System.arraycopy(y, 0, z, 0, 3);
for(int i=0;i<z.length;i++){
System.out.println("z["+i+"]="+z[i]);
}
//Java中的順序結(jié)構(gòu)
//多維數(shù)組
//每個(gè)多維數(shù)組有2個(gè)一維數(shù)組,每個(gè)一維數(shù)組有3個(gè)元素
int [][]xx=new int [2][3];
xx[0][0]=3;
xx[1][2]=6;
for(int i=0;i<xx.length;i++){
for(int j=0;j<xx[i].length;j++){
System.out.println("xx["+i+"]["+j+"]="+xx[i][j]);
}
}
}
}
二、面向?qū)ο?/h1>
1.特點(diǎn):適應(yīng)性強(qiáng),可拓展性好;從任務(wù)的執(zhí)行者變成了指揮者
2.特征:
封裝:封裝是將不需要對(duì)外提供的屬性和細(xì)節(jié)隱藏,僅對(duì)外提供公共的訪(fǎng)問(wèn)方式提高了代碼的安全性,復(fù)用性和可維護(hù)性
繼承:?一個(gè)類(lèi)只能有一個(gè)父類(lèi),單繼承,多實(shí)現(xiàn),可以分層繼承
?子類(lèi)具有父類(lèi)的非私有屬性和方法
?被final修飾的類(lèi)不能被繼承
?讓類(lèi)與類(lèi)之間產(chǎn)生關(guān)系,繼承是多態(tài)的前提
多態(tài):一種事物的多種形態(tài),多態(tài)存在的三個(gè)必要條件
①有繼承關(guān)系(接口與實(shí)現(xiàn)類(lèi)也能形成多態(tài)關(guān)系)
②子類(lèi)強(qiáng)制重寫(xiě)父類(lèi)抽象方法
③父類(lèi)引用方法時(shí),指向子類(lèi)對(duì)象的方法
3.類(lèi)與對(duì)象:
類(lèi):是一堆有共同特征的事物的描述,是概念,定義。
對(duì)象:是某類(lèi)事物的具體體現(xiàn),也稱(chēng)實(shí)例。
?類(lèi)是對(duì)象的抽象,對(duì)象是類(lèi)的具體體現(xiàn)。
4.成員方法:在類(lèi)里面的方法叫全局方法
成員屬性:在類(lèi)里面的屬性叫全局屬性
局部變量:類(lèi)內(nèi)的方法中定義的變量(必須手動(dòng)賦值)
成員變量:類(lèi)中成員位置定義的變量(系統(tǒng)自動(dòng)初始化)
int類(lèi)型默認(rèn)是0;double類(lèi)型默認(rèn)是0.0;String類(lèi)型默認(rèn)是null
成員位置和局部變量的區(qū)別:定義位置不同,生命周期不同,初始化值不同,內(nèi)存中的存儲(chǔ)位置不同
5.this在本類(lèi)中調(diào)用自己的屬性和方法
super在子類(lèi)中調(diào)用父類(lèi)的屬性和方法
6.this作為對(duì)象的默認(rèn)引用有兩種情況:
①構(gòu)造器中引用該構(gòu)造器正在初始化的對(duì)象
②在方法中引用調(diào)用該方法的對(duì)象
7.局部變量隱藏成員變量時(shí),要是用this關(guān)鍵字
public class Preson {
//屬性類(lèi)型 屬性名 類(lèi)的成員變量
private int age;
private String name;
//方法返回值類(lèi)型 方法名(參數(shù)列表) 類(lèi)的成員函數(shù)
void shout(){
//方法的局部變量
// int age=18;
//訪(fǎng)問(wèn)到的是方法中的局部變量
System.out.println("My age is "+age);
}
//加void這個(gè)方法不執(zhí)行
// public Preson(){
// System.out.println("the constructorl is calling!");
// }
// public Preson (String name){
// name=name;
// }
// public Preson(String name,int age){
// name=name;
// age=age;//第一個(gè)age是成員變量,第二個(gè)age是
// }
public void setAge(int age) {
if (age<0) {
return;
}
age = age;
}
public int getAge() {
return age;
}
public void getSomeOne(Preson p){
p.shout();
}
public static void main(String [] args){
//當(dāng)一個(gè)對(duì)象被創(chuàng)建時(shí),會(huì)對(duì)其中各種類(lèi)型的成員變量自動(dòng)進(jìn)行初始化賦值
Preson p1=new Preson();
Preson p2=new Preson();
p1.age=-2;
p1.shout();
p2.shout();
p1.getSomeOne(p2);
String s1=new String("abc");
String s2=new String("abc");
String s3=s1;
//s1==s2----->equels比較地址值相等,倆個(gè)對(duì)象中的內(nèi)容是否相等
//s1==s3----->==比較值相等
if (s1==s3) {
System.out.println("true");
}else {
System.out.println("false");
}
}
}
class Container{
Component comp;
public void addComponent(Component comp){
// this.comp=comp;
//在構(gòu)造方法里傳入一個(gè)容器(這個(gè)容器屬于這個(gè)組件)
// comp=new Component(new Container());
//this在本類(lèi)中調(diào)用自己的屬性和方法
comp=new Component(this);
}
}
class Component{
Container con;
public Component(Container con){
this.con=con;
}
}
三、垃圾回收過(guò)程分析
?C++中的析構(gòu)方法
?finalize():是Object中的方法,當(dāng)垃圾回收器將回收對(duì)象從內(nèi)存中清除出去之前會(huì)調(diào)用finalize(),但此時(shí)并不代表該回收對(duì)象一定會(huì)“死亡”,還有機(jī)會(huì)“逃脫
?System.gc的作用:將創(chuàng)建完的對(duì)象垃圾回收
public Preson(){
System.out.println("the constructorl is calling!");
}
public void finalize(){
System.out.println("Object is going!");
}
public static void main(String [] args){
new Preson();
new Preson();
//垃圾回收器
System.gc();
}
image
四、static關(guān)鍵字
1.作用:靜態(tài)修飾符 可以修飾成員變量和成員方法
2.static關(guān)鍵字特點(diǎn):
⑴隨著類(lèi)的加載而加載
⑵優(yōu)先于對(duì)象存在
⑶被類(lèi)的所有對(duì)象共享
⑷這也是我們判斷是否使用靜態(tài)關(guān)鍵字的條件
⑸可以通過(guò)類(lèi)名調(diào)用
3.static關(guān)鍵字注意事項(xiàng)
⑴在靜態(tài)方法中是沒(méi)有this和super關(guān)鍵字的
⑵靜態(tài)方法只能訪(fǎng)問(wèn)靜態(tài)的成員變量和靜態(tài)的成員方法,而不能直接訪(fǎng)問(wèn)類(lèi)中的非靜態(tài)成員,對(duì)于非靜態(tài)的方法和變量,需要先創(chuàng)建類(lèi)的實(shí)例對(duì)象才能使用,而靜態(tài)方法不需要?jiǎng)?chuàng)建任何對(duì)象
public class PassParam {
int x;
public static void main(String [] args){
// int x=5;
// change(x);
// System.out.println(x);
PassParam obj=new PassParam();
obj.x=5;
change(obj);
System.out.println(obj.x);
int []x=new int[1];
x[0]=5;
//棧中對(duì)象的變量等于堆中對(duì)象的首地址
change(x);
System.out.println(x[0]);
}
// public static void change(int x){
// x=3;
// }
public static void change(PassParam obj){
obj.x=3;
}
public static void change(int[] x){
x[0]=3;
}
}
class Chinese{
//不加static每次調(diào)用這個(gè)方法都會(huì)產(chǎn)生一個(gè)對(duì)象,直到消耗完才結(jié)束
//加static在調(diào)用這個(gè)方法前就創(chuàng)建完成對(duì)象
static Chinese objRet=new Chinese();
//被static修飾的成員變量
private static int count=0;
static String country="中國(guó)";
static {
count=4;
System.out.println("static code");
}
String name;
int age;
//靜態(tài)方法不能訪(fǎng)問(wèn)非靜態(tài)的成員方法objRet
public static Chinese getInstance(){
return objRet;
}
public Chinese(){
System.out.println(++count);
}
//靜態(tài)的方法
static void sing(){
System.out.println("啊");
}
//非靜態(tài)的成員方法使用時(shí)要?jiǎng)?chuàng)建一個(gè)對(duì)象,就可以訪(fǎng)問(wèn)靜態(tài)的成員變量和非靜態(tài)的成員變量
void singOutCountry(){
//類(lèi) 對(duì)象 方法
System.out.println(country);
sing();
}
}
class TextChinese{
public static void main(String []args){
System.out.println(Chinese.country);
Chinese chinese=new Chinese();
chinese.singOutCountry();
System.out.println(chinese.country);
//類(lèi)名.方法 JVM虛擬機(jī)在用到這個(gè)類(lèi)的時(shí)候加載
Chinese.sing();
//Chinese這個(gè)類(lèi)的實(shí)例對(duì)象,通過(guò)實(shí)例對(duì)象來(lái)調(diào)用靜態(tài)的方法
System.out.println("begin");
new Chinese().sing();
System.out.println("end");
new Chinese().singOutCountry();
Chinese obj1=chinese.getInstance();
Chinese obj2=chinese.getInstance();
//如果相等為true,不相等為flase
System.out.println(obj1==obj2);
}
}
五、內(nèi)部類(lèi)
1.定義:一個(gè)類(lèi)中還包含著另外一個(gè)類(lèi)
2.分類(lèi):
?成員內(nèi)部類(lèi):內(nèi)部類(lèi)寫(xiě)在了類(lèi)中成員成員方法的外部,跟成員變量成員方法是同一級(jí)別
?局部?jī)?nèi)部類(lèi):在方法中定義的內(nèi)部類(lèi)(不加修飾符,只能在當(dāng)前方法中使用)在局部?jī)?nèi)部類(lèi)中訪(fǎng)問(wèn)局部變量加final關(guān)鍵字
?靜態(tài)內(nèi)部類(lèi):使用static修飾的成員內(nèi)部類(lèi)
?匿名內(nèi)部類(lèi):沒(méi)有名字的內(nèi)部類(lèi)
3.匿名內(nèi)部類(lèi)的格式:new的后面,用其隱含實(shí)現(xiàn)一個(gè)抽象類(lèi)的子類(lèi)或接口的實(shí)現(xiàn)一個(gè)類(lèi)
六、類(lèi)的繼承
1.通過(guò)繼承可以簡(jiǎn)化類(lèi)的定義
2.Java支持單繼承,不允許多重繼承
3.可以多重繼承,一個(gè)類(lèi)可以繼承某一個(gè)類(lèi)的子類(lèi),類(lèi)B繼承類(lèi)A,類(lèi)C繼承類(lèi)B,那么類(lèi)C間接繼承類(lèi)A
4.子類(lèi)繼承父類(lèi)所有的成員方法和成員變量,但是不繼承父類(lèi)的構(gòu)造方法。在子類(lèi)的構(gòu)造方法中可以使用super語(yǔ)句(參數(shù)列表)調(diào)用父類(lèi)的構(gòu)造方法
5.如果子類(lèi)的構(gòu)造方法中沒(méi)有顯示的調(diào)用父類(lèi)中的構(gòu)造方法,也沒(méi)有使用this關(guān)鍵字調(diào)用重載的其他構(gòu)造方法,則在產(chǎn)生子類(lèi)的實(shí)例對(duì)象時(shí),系統(tǒng)默認(rèn)調(diào)用父類(lèi)無(wú)參數(shù)的構(gòu)造方法
class Person {
public String name="unknow";
public int age=-1;
//無(wú)參構(gòu)造
public Person(){
}
//有參構(gòu)造
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void getInfo(){
System.out.println("name:"+name+",age:"+age);
}
}
class Student extends Person{
//不用重寫(xiě)父類(lèi)中的成員變量和成員方法
public String school="unknow";
//在調(diào)用這個(gè)構(gòu)造函數(shù)之前先調(diào)用Person構(gòu)造方法
public Student(){
//調(diào)用父類(lèi)的構(gòu)造函數(shù)
super();
// super("李四,18");
}
public Student (String name,int age,String school){
//this和super必須首先調(diào)用,否則會(huì)報(bào)錯(cuò)
super(name, age);
this.school=school;
}
public void getInfo(){
System.out.println("school:"+school+",name:"+name+",age:"+age);
}
public void study(){
}
}
class TextStudent {
public static void main(String []args){
//創(chuàng)建子類(lèi)的對(duì)象
Student student=new Student();
student.name="zhangsan";
student.age=8;
//繼承父類(lèi)中的getInfo()
student.getInfo();
}
}
七、final關(guān)鍵字
1.在Java中聲明類(lèi)、屬性、方法時(shí),使用關(guān)鍵字final來(lái)修飾
2.final修飾的類(lèi)不能被繼承,方法不能被子類(lèi)重寫(xiě)
3.final修飾的變量是常量,只能賦值一次
4.public ,static ,final共同標(biāo)記常量時(shí),這個(gè)常量就成了全局的常量
5.方法中定義的內(nèi)置類(lèi)只能訪(fǎng)問(wèn)該方法內(nèi)的final類(lèi)型的局部變量,final修飾的變量是常量,它的生命周期相超出方法運(yùn)行的生命周期,將一個(gè)形參定義成final也是可以的,限定了我們?cè)诜椒ㄖ行揎椥问絽?shù)的值
//final修飾的類(lèi)不能被繼承
//final class Person
class Person {
//被final修飾的常量不能被修改,如果要是用使用就要?jiǎng)?chuàng)建實(shí)例,或者是加static
public final String x="ABC";
//final修飾的方法不會(huì)走下面的getInfo
//public final void getInfo()
public void getInfo(){
System.out.println("name:"+name+",age:"+age);
}
}
八、抽象類(lèi)
1.定義:Java中可以定義一些不含方法體的方法,它的方法體的實(shí)現(xiàn)交給該類(lèi)的子類(lèi)根據(jù)自己的情況實(shí)現(xiàn),這樣的方法就叫抽象方法,包含抽象方法的類(lèi)叫抽象類(lèi)。
2.特點(diǎn):?用abstract修飾的方法,沒(méi)有方法體,叫抽象方法
?抽象類(lèi)不能被實(shí)例化,也不能用new關(guān)鍵字去產(chǎn)生對(duì)象
?抽象方法只需要聲明,不需要實(shí)現(xiàn)
?含有抽象方法的類(lèi)必須別聲明為抽象類(lèi),抽象類(lèi)的子類(lèi)必須覆蓋所有的抽象方法后才能被實(shí)例化,否則這個(gè)子類(lèi)還是個(gè)抽象類(lèi)
?有抽象方法一定是抽象類(lèi)或接口
?抽象類(lèi)不一定有抽象方法,接口一定有抽象方法
?抽象類(lèi)中可以有普通方法,靜態(tài)方法,成員變量,接口只能有抽象方法和靜態(tài)常量
九、接口(interface)
1.定義:因?yàn)橛袝r(shí)程序無(wú)法準(zhǔn)確地描述出類(lèi)的行為,所以用接口來(lái)補(bǔ)充
2.特點(diǎn):
⑴接口不能實(shí)例化(不能產(chǎn)生對(duì)象)
接口可以按照多態(tài)的方式,由具體的子類(lèi)實(shí)例化,這也是多態(tài)的一種,接口多態(tài)。
⑵接口子類(lèi)的特點(diǎn)
要么是抽象類(lèi),要么是普通類(lèi),如果是普通類(lèi),必須重寫(xiě)接口中的所有抽象方法。
⑶接口采用關(guān)鍵字interface定義。
⑷接口使用implements實(shí)現(xiàn)。
⑸如果一個(gè)類(lèi)實(shí)現(xiàn)了某個(gè)接口,那么該類(lèi)被稱(chēng)為實(shí)現(xiàn)類(lèi)
⑹接口中的成員都是用public來(lái)修飾的,接口里的變量默認(rèn)是用public static final標(biāo)識(shí)的
十、對(duì)象的類(lèi)型轉(zhuǎn)換
1.子類(lèi)對(duì)象可以自動(dòng)轉(zhuǎn)換為父類(lèi)
2.父類(lèi)轉(zhuǎn)換成子類(lèi)必須使用強(qiáng)制轉(zhuǎn)換
3.instanceof操作符可以用它來(lái)判斷一個(gè)實(shí)例對(duì)象是否屬于一個(gè)類(lèi)
十一、異常
1.定義:程序中遇到的非致命的錯(cuò)誤,而不是編譯時(shí)的語(yǔ)法錯(cuò)誤,如程序要打開(kāi)一個(gè)不存在的文件、網(wǎng)絡(luò)、連接中斷、操作數(shù)越界、裝載一個(gè)不存在的類(lèi)
2.Throwable繼承層次結(jié)構(gòu),可見(jiàn)分成兩大類(lèi)Error和Exception:
Error(錯(cuò)誤):指程序無(wú)法恢復(fù)的異常情況,表示運(yùn)行應(yīng)用程序中較嚴(yán)重的問(wèn)題;發(fā)生于虛擬機(jī)自身、或者在虛擬機(jī)試圖執(zhí)行應(yīng)用時(shí),如Virtual MachineError(Java虛擬機(jī)運(yùn)行錯(cuò)誤)、NoClassDefFoundError(類(lèi)定義錯(cuò)誤);屬于不可查異常,即不強(qiáng)制程序員必須處理,即使不處理也不會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤。
Exception(異常):指程序有可能恢復(fù)的異常情況,表示程序本身可以處理的異常。又分兩大類(lèi):
?RuntimeException(運(yùn)行時(shí)異常):由程序自身的問(wèn)題導(dǎo)致產(chǎn)生的異常;如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標(biāo)越界異常);屬于不可查異常。
?非運(yùn)行時(shí)異常:由程序外部的問(wèn)題引起的異常;除了RuntimeException以外的異常,如FileNotFoundException(文件不存在異常);屬于可查異常,即強(qiáng)制程序員必須進(jìn)行處理,如果不進(jìn)行處理則會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤。
3.常見(jiàn)的異常處理機(jī)制有:
捕捉異常:由系統(tǒng)自動(dòng)拋出異常,即try捕獲異常->catch處理異常->finally 最終處理
拋出異常:在方法中將異常對(duì)象顯性地拋出,之后異常會(huì)沿著調(diào)用層次向上拋出,交由調(diào)用它的方法來(lái)處理。配合throws聲明拋出的異常和throw拋出異常
自定義異常:繼承Execption類(lèi)或其子類(lèi)
十二、多線(xiàn)程
1.進(jìn)程
⑴定義:在多任務(wù)系統(tǒng)中,每個(gè)獨(dú)立執(zhí)行的程序,也就是進(jìn)程,即“正在進(jìn)行的程序”,我們現(xiàn)在使用的操作系統(tǒng)一般都是多任務(wù)的,即能夠同時(shí)執(zhí)行多個(gè)應(yīng)用程序,實(shí)際情況是,操作系統(tǒng)負(fù)責(zé)對(duì)CPU等設(shè)備的資源進(jìn)行分配和管理,雖然這些設(shè)備在某一時(shí)刻只能做一件事,但以非常小的時(shí)間間隔交替執(zhí)行多個(gè)程序,就可以給人以同時(shí)執(zhí)行多個(gè)程序的感覺(jué)
⑵一個(gè)進(jìn)程中又可以包含一個(gè)或多個(gè)線(xiàn)程
2.線(xiàn)程
⑴一個(gè)線(xiàn)程就是一個(gè)程序內(nèi)部的一條執(zhí)行線(xiàn)索,如果要一程序中實(shí)現(xiàn)多段代碼同時(shí)交替運(yùn)行,就需產(chǎn)生多個(gè)線(xiàn)程,并指定每個(gè)線(xiàn)程上所要運(yùn)行的程序代碼段,就是多線(xiàn)程
3.后臺(tái)線(xiàn)程與聯(lián)合線(xiàn)程
⑴如果我們對(duì)某個(gè)線(xiàn)程對(duì)象在啟動(dòng)(調(diào)用start方法)之前調(diào)用了setDaemon(true)方法,這個(gè)線(xiàn)程就變成了后臺(tái)線(xiàn)程。
⑵對(duì)于Java程序來(lái)說(shuō),只要還有一個(gè)前臺(tái)線(xiàn)程在運(yùn)行,這個(gè)進(jìn)程就不會(huì)結(jié)束,如果一個(gè)進(jìn)程中只有后臺(tái)線(xiàn)程在運(yùn)行,這個(gè)進(jìn)程就會(huì)結(jié)束。
4.用Thread類(lèi)創(chuàng)建線(xiàn)程
⑴要將一段代碼在一個(gè)新的線(xiàn)程上運(yùn)行,該代碼應(yīng)該在一個(gè)類(lèi)的run函數(shù)中,并且run函數(shù)所在的類(lèi)是Thread類(lèi)的子類(lèi)。倒過(guò)來(lái)看,我們要實(shí)現(xiàn)多線(xiàn)程,必須編寫(xiě)一個(gè)繼承了Thread類(lèi)的子類(lèi),子類(lèi)要覆蓋Thread類(lèi)中的run函數(shù),在子類(lèi)的run函數(shù)中調(diào)用想在新線(xiàn)程上的運(yùn)行的程序代碼。
⑵啟動(dòng)一個(gè)新的線(xiàn)程,我們不是直接調(diào)用Thread的子類(lèi)對(duì)象的run方法,而是調(diào)用Thread的子類(lèi)對(duì)象的start(從Thread類(lèi)繼承到的)方法,Thread類(lèi)對(duì)象的start方法將產(chǎn)生一個(gè)新的線(xiàn)程,并在該線(xiàn)程上運(yùn)行該Thread的類(lèi)對(duì)象中的run方法,根據(jù)面向?qū)ο蟮倪\(yùn)行時(shí)的多態(tài)性,在該線(xiàn)程上實(shí)際運(yùn)行的是Thread的子類(lèi)(也就是我們寫(xiě)的那個(gè)類(lèi))對(duì)象中的run方法
⑶由于線(xiàn)程的代碼段在run方法中,那么該方法執(zhí)行完成以后,線(xiàn)程也就相應(yīng)的結(jié)束了,因而我們可以通過(guò)控制run方法中循環(huán)的條件來(lái)控制線(xiàn)程的結(jié)束
5.后臺(tái)線(xiàn)程和聯(lián)合線(xiàn)程
⑴如果我們對(duì)某個(gè)線(xiàn)程對(duì)象在啟動(dòng)(調(diào)用start方法)之前調(diào)用了setDaemon(true)方法,這個(gè)線(xiàn)程就變成了后臺(tái)線(xiàn)程。
⑵對(duì)java程序來(lái)說(shuō),只要還有一個(gè)前臺(tái)線(xiàn)程在運(yùn)行,這個(gè)進(jìn)程就不會(huì)結(jié)束,如果一個(gè)進(jìn)程中只有后臺(tái)線(xiàn)程運(yùn)行,這個(gè)進(jìn)程就會(huì)結(jié)束
⑶pp.join()的作用是把pp所對(duì)應(yīng)的線(xiàn)程合并到調(diào)用pp.join()語(yǔ)句的線(xiàn)程中
6.使用Runnable接口創(chuàng)建多線(xiàn)程
⑴適合多個(gè)相同程序代碼的線(xiàn)程去處理同一資源的情況,把虛擬CPU(線(xiàn)程)同程序的代碼,數(shù)據(jù)有效分離,較好的體現(xiàn)了面向?qū)ο蟮脑O(shè)計(jì)思想
⑵可以避免由于java的單繼承特性帶來(lái)的局限。我們經(jīng)常碰到這樣一種情況,即當(dāng)我們要將已經(jīng)繼承了某一個(gè)類(lèi)的子類(lèi)放入多線(xiàn)程中,由于一個(gè)類(lèi)不能同時(shí)有兩個(gè)父類(lèi),所以不能用繼承Tread類(lèi)的方式,那么,這個(gè)類(lèi)就只能采用實(shí)現(xiàn)Runnable
⑶當(dāng)線(xiàn)程被構(gòu)造時(shí),需要的代碼和數(shù)據(jù)通過(guò)一個(gè)對(duì)象作為構(gòu)造函數(shù)實(shí)參傳遞進(jìn)去,這個(gè)對(duì)象就是一個(gè)實(shí)現(xiàn)了Runnable接口類(lèi)的實(shí)例
⑷幾乎所有多線(xiàn)程應(yīng)用都可以用Runnable接口方式
7.多線(xiàn)程在實(shí)際中的應(yīng)用
網(wǎng)絡(luò)聊天程序的收發(fā)
⑴如果一方從鍵盤(pán)上讀取了數(shù)據(jù)并發(fā)送給了對(duì)方,程序運(yùn)行到"讀取對(duì)方回送的數(shù)據(jù)"并一直等待對(duì)方回送數(shù)據(jù),如果對(duì)方?jīng)]有回應(yīng),程序不能再做任何其他事情,這時(shí)程序處于堵塞狀態(tài),即使用戶(hù)想正常終止程序運(yùn)行都不可能,更不能實(shí)現(xiàn)"再給對(duì)方發(fā)送一條信息,催促對(duì)方趕快答應(yīng)"這樣的事情
⑵如果程序沒(méi)有事先從鍵盤(pán)上讀取數(shù)據(jù)并向外發(fā)送,程序?qū)⒁恢痹?從鍵盤(pán)上讀取數(shù)據(jù)"處堵塞,即使有數(shù)據(jù)從網(wǎng)上發(fā)送過(guò)來(lái),程序無(wú)法到達(dá)"讀取對(duì)方回送的數(shù)據(jù)"處,程序?qū)⒉荒苁盏絼e處先主動(dòng)發(fā)送過(guò)來(lái)的數(shù)據(jù)
表記錄的復(fù)制的中途取消
www服務(wù)器為每一個(gè)來(lái)訪(fǎng)者都建立專(zhuān)線(xiàn)服務(wù)
8.多線(xiàn)程的同步問(wèn)題
線(xiàn)程安全
線(xiàn)程安全就是當(dāng)多個(gè)線(xiàn)程訪(fǎng)問(wèn)一個(gè)對(duì)象時(shí),如果不用考慮這些線(xiàn)程在運(yùn)行時(shí)環(huán)境下的調(diào)度和交替執(zhí)行,也不需要進(jìn)行額外的同步,或者在調(diào)用方進(jìn)行任何其他的協(xié)調(diào)操作,調(diào)用這個(gè)對(duì)象的行為都可以獲得正確的結(jié)果,那這個(gè)對(duì)象是線(xiàn)程安全的。
同步代碼塊
?所謂代碼塊是指用“{}”括起來(lái)的一段代碼,根據(jù)其位置和聲明的不同,可以分為普通代碼塊、構(gòu)造塊、靜態(tài)塊、和同步代碼塊。
?如果在代碼塊前加上 synchronized關(guān)鍵字,則此代碼塊就成為同步代碼塊。
同步函數(shù)
同步函數(shù):當(dāng)一個(gè)函數(shù)是同步執(zhí)行時(shí),那么當(dāng)該函數(shù)被調(diào)用時(shí)不會(huì)立即返回,直到該函數(shù)所要做的事情全都做完了才返回。
死鎖問(wèn)題
死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。此時(shí)稱(chēng)系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱(chēng)為死鎖進(jìn)程。
死鎖的發(fā)生必須具備以下四個(gè)必要條件
①互斥條件:指進(jìn)程對(duì)所分配到的資源進(jìn)行排它性使用,即在一段時(shí)間內(nèi)某資源只由一個(gè)進(jìn)程占用。如果此時(shí)還有其它進(jìn)程請(qǐng)求資源,則請(qǐng)求者只能等待,直至占有資源的進(jìn)程用畢釋放。
②請(qǐng)求和保持條件:指進(jìn)程已經(jīng)保持至少一個(gè)資源,但又提出了新的資源請(qǐng)求,而該資源已被其它進(jìn)程占有,此時(shí)請(qǐng)求進(jìn)程阻塞,但又對(duì)自己已獲得的其它資源保持不放。
③不剝奪條件:指進(jìn)程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時(shí)由自己釋放。
④環(huán)路等待條件:指在發(fā)生死鎖時(shí),必然存在一個(gè)進(jìn)程——資源的環(huán)形鏈,即進(jìn)程集合{P0,P1,P2,···,Pn}中的P0正在等待一個(gè)P1占用的資源;P1正在等待P2占用的資源,……,Pn正在等待已被P0占用的資源。
9.進(jìn)程間的通信
?wait:告訴當(dāng)前線(xiàn)程放棄監(jiān)視器并進(jìn)入睡眠狀態(tài)直到其他線(xiàn)程進(jìn)入同一監(jiān)視器并調(diào)用notify為止
?notify:喚醒同一對(duì)象監(jiān)視器中調(diào)用wait的第一個(gè)線(xiàn)程,并于類(lèi)似飯館有一個(gè)空位后通知所有等候就餐的顧客中的第一位可以入座的情況
?notifyAll:喚醒同一對(duì)象監(jiān)視器中調(diào)用wait的所有線(xiàn)程,具有最高優(yōu)先級(jí)的線(xiàn)程首先被喚醒并執(zhí)行。用于類(lèi)似某個(gè)不定期的培訓(xùn)班終于招生滿(mǎn)額后,通知所有學(xué)員都來(lái)上課的情況
10.線(xiàn)程生命周期的控制
先通過(guò)start()產(chǎn)生一個(gè)線(xiàn)程對(duì)象,這時(shí)線(xiàn)程并不是正真的執(zhí)行,而是會(huì)進(jìn)入Runnable()狀態(tài),然后由Scheduler(調(diào)度器/操作系統(tǒng))來(lái)調(diào)度,正真開(kāi)始執(zhí)行的線(xiàn)程進(jìn)入了Running()狀態(tài),如果這時(shí)run中的方法結(jié)束,線(xiàn)程就結(jié)束了;如果在線(xiàn)程運(yùn)行的過(guò)程中,遇到了synchronized方法,就會(huì)發(fā)生堵塞,會(huì)在鎖中發(fā)生停滯,直到得到對(duì)象的鎖旗標(biāo)之后,重新進(jìn)入Runnable()狀態(tài)(可執(zhí)行狀態(tài)),然后由調(diào)度器統(tǒng)一執(zhí)行;如果得到wait()之后,會(huì)釋放鎖旗標(biāo),進(jìn)入wait()的等待池中,遇到nitify()就會(huì)進(jìn)入監(jiān)視器的等待池中,直到得到對(duì)象的鎖旗標(biāo)之后,重新進(jìn)入Runnable()狀態(tài)(可執(zhí)行狀態(tài)),然后由調(diào)度器統(tǒng)一執(zhí)行。
十三、JAVA API
1.概念
就是JDK中提供各種Java類(lèi),例如:Systom類(lèi)
2.string類(lèi)和stringBuffer類(lèi)
?String類(lèi)對(duì)象中的內(nèi)容,一旦被初始化就不能再改變
?String類(lèi)使用final修飾,所以不能被繼承
?String的內(nèi)存結(jié)構(gòu)很特殊,在內(nèi)存中有個(gè)字符串常量池,所有的字符串存放在字符串常量池中
?StringBuffer類(lèi)用于封裝內(nèi)容可以改變的字符串
區(qū)別:
String:不可變字符串;頻繁操作時(shí),每次都需新開(kāi)辟內(nèi)存,極易造成內(nèi)存浪費(fèi)
StringBuffer:可變字符串、效率低、線(xiàn)程安全;執(zhí)行速度慢
StringBuilder:可變字符串、效率高、線(xiàn)程不安全;執(zhí)行速度快
(1)如果要操作少量的數(shù)據(jù)用 String;
(2)多線(xiàn)程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) StringBuffer;
(3)單線(xiàn)程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) StringBuilder(推薦使用)。
?StringBuffer和StringBuilder類(lèi)的對(duì)象能夠被多次的修改,并且不產(chǎn)生新的未使用對(duì)象。
?StringBuilder類(lèi)在Java5中被提出,它和StringBuffer之間的最大不同在于StringBuilder的方法不是線(xiàn)程安全的(不能同步訪(fǎng)問(wèn))。
?由于StringBuilder相較于StringBuffer有速度優(yōu)勢(shì),所以多數(shù)情況下建議使用StringBuilder類(lèi)。
?然而在應(yīng)用程序要求線(xiàn)程安全的情況下,則必須使用StringBuffer類(lèi)。
構(gòu)造方法:
?String(byte[] bytes, int offset, int length) 通過(guò)使用平臺(tái)的默認(rèn)字符集解碼指定的 byte 子數(shù)組,構(gòu)造一個(gè)新的 String
?equals 判斷內(nèi)容是否相等,區(qū)分大小寫(xiě)
?equalsIgnoreCase 判斷內(nèi)容是否相等,不區(qū)分大小寫(xiě)
?contains 是否包含子字符串
?isEmpty 判斷字符串長(zhǎng)度是否為0
?startsWith 判斷是否以該字符串為前綴
?endsWith 判斷是否以該字符串為后綴
?indexOf 判斷int值對(duì)應(yīng)的字符在該字符串中出現(xiàn)的位置||判斷子字符串在該字符串中出現(xiàn)的位置
?copyValueOf 將字符數(shù)組轉(zhuǎn)換成字符串,可以從off開(kāi)始,到length結(jié)束
?lastIndexOf 獲取最后一個(gè)字符的位置
?subString 截取
?getBytes 轉(zhuǎn)換為byte[]數(shù)組
?tocharArray 轉(zhuǎn)換成字符數(shù)組
?valueOf 將基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換成字符串,byte數(shù)組或char數(shù)組也可以
?toLowerCase 轉(zhuǎn)換成小寫(xiě)
?toUpperCase 轉(zhuǎn)換成大寫(xiě)
?concat 拼接
3.基本數(shù)據(jù)類(lèi)型的對(duì)象包裝類(lèi)
1.特點(diǎn):適應(yīng)性強(qiáng),可拓展性好;從任務(wù)的執(zhí)行者變成了指揮者
2.特征:
封裝:封裝是將不需要對(duì)外提供的屬性和細(xì)節(jié)隱藏,僅對(duì)外提供公共的訪(fǎng)問(wèn)方式提高了代碼的安全性,復(fù)用性和可維護(hù)性
繼承:?一個(gè)類(lèi)只能有一個(gè)父類(lèi),單繼承,多實(shí)現(xiàn),可以分層繼承
?子類(lèi)具有父類(lèi)的非私有屬性和方法
?被final修飾的類(lèi)不能被繼承
?讓類(lèi)與類(lèi)之間產(chǎn)生關(guān)系,繼承是多態(tài)的前提
多態(tài):一種事物的多種形態(tài),多態(tài)存在的三個(gè)必要條件
①有繼承關(guān)系(接口與實(shí)現(xiàn)類(lèi)也能形成多態(tài)關(guān)系)
②子類(lèi)強(qiáng)制重寫(xiě)父類(lèi)抽象方法
③父類(lèi)引用方法時(shí),指向子類(lèi)對(duì)象的方法
3.類(lèi)與對(duì)象:
類(lèi):是一堆有共同特征的事物的描述,是概念,定義。
對(duì)象:是某類(lèi)事物的具體體現(xiàn),也稱(chēng)實(shí)例。
?類(lèi)是對(duì)象的抽象,對(duì)象是類(lèi)的具體體現(xiàn)。
4.成員方法:在類(lèi)里面的方法叫全局方法
成員屬性:在類(lèi)里面的屬性叫全局屬性
局部變量:類(lèi)內(nèi)的方法中定義的變量(必須手動(dòng)賦值)
成員變量:類(lèi)中成員位置定義的變量(系統(tǒng)自動(dòng)初始化)
int類(lèi)型默認(rèn)是0;double類(lèi)型默認(rèn)是0.0;String類(lèi)型默認(rèn)是null
成員位置和局部變量的區(qū)別:定義位置不同,生命周期不同,初始化值不同,內(nèi)存中的存儲(chǔ)位置不同
5.this在本類(lèi)中調(diào)用自己的屬性和方法
super在子類(lèi)中調(diào)用父類(lèi)的屬性和方法
6.this作為對(duì)象的默認(rèn)引用有兩種情況:
①構(gòu)造器中引用該構(gòu)造器正在初始化的對(duì)象
②在方法中引用調(diào)用該方法的對(duì)象
7.局部變量隱藏成員變量時(shí),要是用this關(guān)鍵字
public class Preson {
//屬性類(lèi)型 屬性名 類(lèi)的成員變量
private int age;
private String name;
//方法返回值類(lèi)型 方法名(參數(shù)列表) 類(lèi)的成員函數(shù)
void shout(){
//方法的局部變量
// int age=18;
//訪(fǎng)問(wèn)到的是方法中的局部變量
System.out.println("My age is "+age);
}
//加void這個(gè)方法不執(zhí)行
// public Preson(){
// System.out.println("the constructorl is calling!");
// }
// public Preson (String name){
// name=name;
// }
// public Preson(String name,int age){
// name=name;
// age=age;//第一個(gè)age是成員變量,第二個(gè)age是
// }
public void setAge(int age) {
if (age<0) {
return;
}
age = age;
}
public int getAge() {
return age;
}
public void getSomeOne(Preson p){
p.shout();
}
public static void main(String [] args){
//當(dāng)一個(gè)對(duì)象被創(chuàng)建時(shí),會(huì)對(duì)其中各種類(lèi)型的成員變量自動(dòng)進(jìn)行初始化賦值
Preson p1=new Preson();
Preson p2=new Preson();
p1.age=-2;
p1.shout();
p2.shout();
p1.getSomeOne(p2);
String s1=new String("abc");
String s2=new String("abc");
String s3=s1;
//s1==s2----->equels比較地址值相等,倆個(gè)對(duì)象中的內(nèi)容是否相等
//s1==s3----->==比較值相等
if (s1==s3) {
System.out.println("true");
}else {
System.out.println("false");
}
}
}
class Container{
Component comp;
public void addComponent(Component comp){
// this.comp=comp;
//在構(gòu)造方法里傳入一個(gè)容器(這個(gè)容器屬于這個(gè)組件)
// comp=new Component(new Container());
//this在本類(lèi)中調(diào)用自己的屬性和方法
comp=new Component(this);
}
}
class Component{
Container con;
public Component(Container con){
this.con=con;
}
}
?C++中的析構(gòu)方法
?finalize():是Object中的方法,當(dāng)垃圾回收器將回收對(duì)象從內(nèi)存中清除出去之前會(huì)調(diào)用finalize(),但此時(shí)并不代表該回收對(duì)象一定會(huì)“死亡”,還有機(jī)會(huì)“逃脫
?System.gc的作用:將創(chuàng)建完的對(duì)象垃圾回收
public Preson(){
System.out.println("the constructorl is calling!");
}
public void finalize(){
System.out.println("Object is going!");
}
public static void main(String [] args){
new Preson();
new Preson();
//垃圾回收器
System.gc();
}

1.作用:靜態(tài)修飾符 可以修飾成員變量和成員方法
2.static關(guān)鍵字特點(diǎn):
⑴隨著類(lèi)的加載而加載
⑵優(yōu)先于對(duì)象存在
⑶被類(lèi)的所有對(duì)象共享
⑷這也是我們判斷是否使用靜態(tài)關(guān)鍵字的條件
⑸可以通過(guò)類(lèi)名調(diào)用
3.static關(guān)鍵字注意事項(xiàng)
⑴在靜態(tài)方法中是沒(méi)有this和super關(guān)鍵字的
⑵靜態(tài)方法只能訪(fǎng)問(wèn)靜態(tài)的成員變量和靜態(tài)的成員方法,而不能直接訪(fǎng)問(wèn)類(lèi)中的非靜態(tài)成員,對(duì)于非靜態(tài)的方法和變量,需要先創(chuàng)建類(lèi)的實(shí)例對(duì)象才能使用,而靜態(tài)方法不需要?jiǎng)?chuàng)建任何對(duì)象
public class PassParam {
int x;
public static void main(String [] args){
// int x=5;
// change(x);
// System.out.println(x);
PassParam obj=new PassParam();
obj.x=5;
change(obj);
System.out.println(obj.x);
int []x=new int[1];
x[0]=5;
//棧中對(duì)象的變量等于堆中對(duì)象的首地址
change(x);
System.out.println(x[0]);
}
// public static void change(int x){
// x=3;
// }
public static void change(PassParam obj){
obj.x=3;
}
public static void change(int[] x){
x[0]=3;
}
}
class Chinese{
//不加static每次調(diào)用這個(gè)方法都會(huì)產(chǎn)生一個(gè)對(duì)象,直到消耗完才結(jié)束
//加static在調(diào)用這個(gè)方法前就創(chuàng)建完成對(duì)象
static Chinese objRet=new Chinese();
//被static修飾的成員變量
private static int count=0;
static String country="中國(guó)";
static {
count=4;
System.out.println("static code");
}
String name;
int age;
//靜態(tài)方法不能訪(fǎng)問(wèn)非靜態(tài)的成員方法objRet
public static Chinese getInstance(){
return objRet;
}
public Chinese(){
System.out.println(++count);
}
//靜態(tài)的方法
static void sing(){
System.out.println("啊");
}
//非靜態(tài)的成員方法使用時(shí)要?jiǎng)?chuàng)建一個(gè)對(duì)象,就可以訪(fǎng)問(wèn)靜態(tài)的成員變量和非靜態(tài)的成員變量
void singOutCountry(){
//類(lèi) 對(duì)象 方法
System.out.println(country);
sing();
}
}
class TextChinese{
public static void main(String []args){
System.out.println(Chinese.country);
Chinese chinese=new Chinese();
chinese.singOutCountry();
System.out.println(chinese.country);
//類(lèi)名.方法 JVM虛擬機(jī)在用到這個(gè)類(lèi)的時(shí)候加載
Chinese.sing();
//Chinese這個(gè)類(lèi)的實(shí)例對(duì)象,通過(guò)實(shí)例對(duì)象來(lái)調(diào)用靜態(tài)的方法
System.out.println("begin");
new Chinese().sing();
System.out.println("end");
new Chinese().singOutCountry();
Chinese obj1=chinese.getInstance();
Chinese obj2=chinese.getInstance();
//如果相等為true,不相等為flase
System.out.println(obj1==obj2);
}
}
1.定義:一個(gè)類(lèi)中還包含著另外一個(gè)類(lèi)
2.分類(lèi):
?成員內(nèi)部類(lèi):內(nèi)部類(lèi)寫(xiě)在了類(lèi)中成員成員方法的外部,跟成員變量成員方法是同一級(jí)別
?局部?jī)?nèi)部類(lèi):在方法中定義的內(nèi)部類(lèi)(不加修飾符,只能在當(dāng)前方法中使用)在局部?jī)?nèi)部類(lèi)中訪(fǎng)問(wèn)局部變量加final關(guān)鍵字
?靜態(tài)內(nèi)部類(lèi):使用static修飾的成員內(nèi)部類(lèi)
?匿名內(nèi)部類(lèi):沒(méi)有名字的內(nèi)部類(lèi)
3.匿名內(nèi)部類(lèi)的格式:new的后面,用其隱含實(shí)現(xiàn)一個(gè)抽象類(lèi)的子類(lèi)或接口的實(shí)現(xiàn)一個(gè)類(lèi)
1.通過(guò)繼承可以簡(jiǎn)化類(lèi)的定義
2.Java支持單繼承,不允許多重繼承
3.可以多重繼承,一個(gè)類(lèi)可以繼承某一個(gè)類(lèi)的子類(lèi),類(lèi)B繼承類(lèi)A,類(lèi)C繼承類(lèi)B,那么類(lèi)C間接繼承類(lèi)A
4.子類(lèi)繼承父類(lèi)所有的成員方法和成員變量,但是不繼承父類(lèi)的構(gòu)造方法。在子類(lèi)的構(gòu)造方法中可以使用super語(yǔ)句(參數(shù)列表)調(diào)用父類(lèi)的構(gòu)造方法
5.如果子類(lèi)的構(gòu)造方法中沒(méi)有顯示的調(diào)用父類(lèi)中的構(gòu)造方法,也沒(méi)有使用this關(guān)鍵字調(diào)用重載的其他構(gòu)造方法,則在產(chǎn)生子類(lèi)的實(shí)例對(duì)象時(shí),系統(tǒng)默認(rèn)調(diào)用父類(lèi)無(wú)參數(shù)的構(gòu)造方法
class Person {
public String name="unknow";
public int age=-1;
//無(wú)參構(gòu)造
public Person(){
}
//有參構(gòu)造
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void getInfo(){
System.out.println("name:"+name+",age:"+age);
}
}
class Student extends Person{
//不用重寫(xiě)父類(lèi)中的成員變量和成員方法
public String school="unknow";
//在調(diào)用這個(gè)構(gòu)造函數(shù)之前先調(diào)用Person構(gòu)造方法
public Student(){
//調(diào)用父類(lèi)的構(gòu)造函數(shù)
super();
// super("李四,18");
}
public Student (String name,int age,String school){
//this和super必須首先調(diào)用,否則會(huì)報(bào)錯(cuò)
super(name, age);
this.school=school;
}
public void getInfo(){
System.out.println("school:"+school+",name:"+name+",age:"+age);
}
public void study(){
}
}
class TextStudent {
public static void main(String []args){
//創(chuàng)建子類(lèi)的對(duì)象
Student student=new Student();
student.name="zhangsan";
student.age=8;
//繼承父類(lèi)中的getInfo()
student.getInfo();
}
}
1.在Java中聲明類(lèi)、屬性、方法時(shí),使用關(guān)鍵字final來(lái)修飾
2.final修飾的類(lèi)不能被繼承,方法不能被子類(lèi)重寫(xiě)
3.final修飾的變量是常量,只能賦值一次
4.public ,static ,final共同標(biāo)記常量時(shí),這個(gè)常量就成了全局的常量
5.方法中定義的內(nèi)置類(lèi)只能訪(fǎng)問(wèn)該方法內(nèi)的final類(lèi)型的局部變量,final修飾的變量是常量,它的生命周期相超出方法運(yùn)行的生命周期,將一個(gè)形參定義成final也是可以的,限定了我們?cè)诜椒ㄖ行揎椥问絽?shù)的值
//final修飾的類(lèi)不能被繼承
//final class Person
class Person {
//被final修飾的常量不能被修改,如果要是用使用就要?jiǎng)?chuàng)建實(shí)例,或者是加static
public final String x="ABC";
//final修飾的方法不會(huì)走下面的getInfo
//public final void getInfo()
public void getInfo(){
System.out.println("name:"+name+",age:"+age);
}
}
1.定義:Java中可以定義一些不含方法體的方法,它的方法體的實(shí)現(xiàn)交給該類(lèi)的子類(lèi)根據(jù)自己的情況實(shí)現(xiàn),這樣的方法就叫抽象方法,包含抽象方法的類(lèi)叫抽象類(lèi)。
2.特點(diǎn):?用abstract修飾的方法,沒(méi)有方法體,叫抽象方法
?抽象類(lèi)不能被實(shí)例化,也不能用new關(guān)鍵字去產(chǎn)生對(duì)象
?抽象方法只需要聲明,不需要實(shí)現(xiàn)
?含有抽象方法的類(lèi)必須別聲明為抽象類(lèi),抽象類(lèi)的子類(lèi)必須覆蓋所有的抽象方法后才能被實(shí)例化,否則這個(gè)子類(lèi)還是個(gè)抽象類(lèi)
?有抽象方法一定是抽象類(lèi)或接口
?抽象類(lèi)不一定有抽象方法,接口一定有抽象方法
?抽象類(lèi)中可以有普通方法,靜態(tài)方法,成員變量,接口只能有抽象方法和靜態(tài)常量
1.定義:因?yàn)橛袝r(shí)程序無(wú)法準(zhǔn)確地描述出類(lèi)的行為,所以用接口來(lái)補(bǔ)充
2.特點(diǎn):
⑴接口不能實(shí)例化(不能產(chǎn)生對(duì)象)
接口可以按照多態(tài)的方式,由具體的子類(lèi)實(shí)例化,這也是多態(tài)的一種,接口多態(tài)。
⑵接口子類(lèi)的特點(diǎn)
要么是抽象類(lèi),要么是普通類(lèi),如果是普通類(lèi),必須重寫(xiě)接口中的所有抽象方法。
⑶接口采用關(guān)鍵字interface定義。
⑷接口使用implements實(shí)現(xiàn)。
⑸如果一個(gè)類(lèi)實(shí)現(xiàn)了某個(gè)接口,那么該類(lèi)被稱(chēng)為實(shí)現(xiàn)類(lèi)
⑹接口中的成員都是用public來(lái)修飾的,接口里的變量默認(rèn)是用public static final標(biāo)識(shí)的
1.子類(lèi)對(duì)象可以自動(dòng)轉(zhuǎn)換為父類(lèi)
2.父類(lèi)轉(zhuǎn)換成子類(lèi)必須使用強(qiáng)制轉(zhuǎn)換
3.instanceof操作符可以用它來(lái)判斷一個(gè)實(shí)例對(duì)象是否屬于一個(gè)類(lèi)
1.定義:程序中遇到的非致命的錯(cuò)誤,而不是編譯時(shí)的語(yǔ)法錯(cuò)誤,如程序要打開(kāi)一個(gè)不存在的文件、網(wǎng)絡(luò)、連接中斷、操作數(shù)越界、裝載一個(gè)不存在的類(lèi)
2.Throwable繼承層次結(jié)構(gòu),可見(jiàn)分成兩大類(lèi)Error和Exception:
Error(錯(cuò)誤):指程序無(wú)法恢復(fù)的異常情況,表示運(yùn)行應(yīng)用程序中較嚴(yán)重的問(wèn)題;發(fā)生于虛擬機(jī)自身、或者在虛擬機(jī)試圖執(zhí)行應(yīng)用時(shí),如Virtual MachineError(Java虛擬機(jī)運(yùn)行錯(cuò)誤)、NoClassDefFoundError(類(lèi)定義錯(cuò)誤);屬于不可查異常,即不強(qiáng)制程序員必須處理,即使不處理也不會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤。
Exception(異常):指程序有可能恢復(fù)的異常情況,表示程序本身可以處理的異常。又分兩大類(lèi):
?RuntimeException(運(yùn)行時(shí)異常):由程序自身的問(wèn)題導(dǎo)致產(chǎn)生的異常;如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標(biāo)越界異常);屬于不可查異常。
?非運(yùn)行時(shí)異常:由程序外部的問(wèn)題引起的異常;除了RuntimeException以外的異常,如FileNotFoundException(文件不存在異常);屬于可查異常,即強(qiáng)制程序員必須進(jìn)行處理,如果不進(jìn)行處理則會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤。
3.常見(jiàn)的異常處理機(jī)制有:
捕捉異常:由系統(tǒng)自動(dòng)拋出異常,即try捕獲異常->catch處理異常->finally 最終處理
拋出異常:在方法中將異常對(duì)象顯性地拋出,之后異常會(huì)沿著調(diào)用層次向上拋出,交由調(diào)用它的方法來(lái)處理。配合throws聲明拋出的異常和throw拋出異常
自定義異常:繼承Execption類(lèi)或其子類(lèi)
⑴定義:在多任務(wù)系統(tǒng)中,每個(gè)獨(dú)立執(zhí)行的程序,也就是進(jìn)程,即“正在進(jìn)行的程序”,我們現(xiàn)在使用的操作系統(tǒng)一般都是多任務(wù)的,即能夠同時(shí)執(zhí)行多個(gè)應(yīng)用程序,實(shí)際情況是,操作系統(tǒng)負(fù)責(zé)對(duì)CPU等設(shè)備的資源進(jìn)行分配和管理,雖然這些設(shè)備在某一時(shí)刻只能做一件事,但以非常小的時(shí)間間隔交替執(zhí)行多個(gè)程序,就可以給人以同時(shí)執(zhí)行多個(gè)程序的感覺(jué)
⑵一個(gè)進(jìn)程中又可以包含一個(gè)或多個(gè)線(xiàn)程
⑴一個(gè)線(xiàn)程就是一個(gè)程序內(nèi)部的一條執(zhí)行線(xiàn)索,如果要一程序中實(shí)現(xiàn)多段代碼同時(shí)交替運(yùn)行,就需產(chǎn)生多個(gè)線(xiàn)程,并指定每個(gè)線(xiàn)程上所要運(yùn)行的程序代碼段,就是多線(xiàn)程
⑴如果我們對(duì)某個(gè)線(xiàn)程對(duì)象在啟動(dòng)(調(diào)用start方法)之前調(diào)用了setDaemon(true)方法,這個(gè)線(xiàn)程就變成了后臺(tái)線(xiàn)程。
⑵對(duì)于Java程序來(lái)說(shuō),只要還有一個(gè)前臺(tái)線(xiàn)程在運(yùn)行,這個(gè)進(jìn)程就不會(huì)結(jié)束,如果一個(gè)進(jìn)程中只有后臺(tái)線(xiàn)程在運(yùn)行,這個(gè)進(jìn)程就會(huì)結(jié)束。
⑴要將一段代碼在一個(gè)新的線(xiàn)程上運(yùn)行,該代碼應(yīng)該在一個(gè)類(lèi)的run函數(shù)中,并且run函數(shù)所在的類(lèi)是Thread類(lèi)的子類(lèi)。倒過(guò)來(lái)看,我們要實(shí)現(xiàn)多線(xiàn)程,必須編寫(xiě)一個(gè)繼承了Thread類(lèi)的子類(lèi),子類(lèi)要覆蓋Thread類(lèi)中的run函數(shù),在子類(lèi)的run函數(shù)中調(diào)用想在新線(xiàn)程上的運(yùn)行的程序代碼。
⑵啟動(dòng)一個(gè)新的線(xiàn)程,我們不是直接調(diào)用Thread的子類(lèi)對(duì)象的run方法,而是調(diào)用Thread的子類(lèi)對(duì)象的start(從Thread類(lèi)繼承到的)方法,Thread類(lèi)對(duì)象的start方法將產(chǎn)生一個(gè)新的線(xiàn)程,并在該線(xiàn)程上運(yùn)行該Thread的類(lèi)對(duì)象中的run方法,根據(jù)面向?qū)ο蟮倪\(yùn)行時(shí)的多態(tài)性,在該線(xiàn)程上實(shí)際運(yùn)行的是Thread的子類(lèi)(也就是我們寫(xiě)的那個(gè)類(lèi))對(duì)象中的run方法
⑶由于線(xiàn)程的代碼段在run方法中,那么該方法執(zhí)行完成以后,線(xiàn)程也就相應(yīng)的結(jié)束了,因而我們可以通過(guò)控制run方法中循環(huán)的條件來(lái)控制線(xiàn)程的結(jié)束
⑴如果我們對(duì)某個(gè)線(xiàn)程對(duì)象在啟動(dòng)(調(diào)用start方法)之前調(diào)用了setDaemon(true)方法,這個(gè)線(xiàn)程就變成了后臺(tái)線(xiàn)程。
⑵對(duì)java程序來(lái)說(shuō),只要還有一個(gè)前臺(tái)線(xiàn)程在運(yùn)行,這個(gè)進(jìn)程就不會(huì)結(jié)束,如果一個(gè)進(jìn)程中只有后臺(tái)線(xiàn)程運(yùn)行,這個(gè)進(jìn)程就會(huì)結(jié)束
⑶pp.join()的作用是把pp所對(duì)應(yīng)的線(xiàn)程合并到調(diào)用pp.join()語(yǔ)句的線(xiàn)程中
⑴適合多個(gè)相同程序代碼的線(xiàn)程去處理同一資源的情況,把虛擬CPU(線(xiàn)程)同程序的代碼,數(shù)據(jù)有效分離,較好的體現(xiàn)了面向?qū)ο蟮脑O(shè)計(jì)思想
⑵可以避免由于java的單繼承特性帶來(lái)的局限。我們經(jīng)常碰到這樣一種情況,即當(dāng)我們要將已經(jīng)繼承了某一個(gè)類(lèi)的子類(lèi)放入多線(xiàn)程中,由于一個(gè)類(lèi)不能同時(shí)有兩個(gè)父類(lèi),所以不能用繼承Tread類(lèi)的方式,那么,這個(gè)類(lèi)就只能采用實(shí)現(xiàn)Runnable
⑶當(dāng)線(xiàn)程被構(gòu)造時(shí),需要的代碼和數(shù)據(jù)通過(guò)一個(gè)對(duì)象作為構(gòu)造函數(shù)實(shí)參傳遞進(jìn)去,這個(gè)對(duì)象就是一個(gè)實(shí)現(xiàn)了Runnable接口類(lèi)的實(shí)例
⑷幾乎所有多線(xiàn)程應(yīng)用都可以用Runnable接口方式
⑴如果一方從鍵盤(pán)上讀取了數(shù)據(jù)并發(fā)送給了對(duì)方,程序運(yùn)行到"讀取對(duì)方回送的數(shù)據(jù)"并一直等待對(duì)方回送數(shù)據(jù),如果對(duì)方?jīng)]有回應(yīng),程序不能再做任何其他事情,這時(shí)程序處于堵塞狀態(tài),即使用戶(hù)想正常終止程序運(yùn)行都不可能,更不能實(shí)現(xiàn)"再給對(duì)方發(fā)送一條信息,催促對(duì)方趕快答應(yīng)"這樣的事情
⑵如果程序沒(méi)有事先從鍵盤(pán)上讀取數(shù)據(jù)并向外發(fā)送,程序?qū)⒁恢痹?從鍵盤(pán)上讀取數(shù)據(jù)"處堵塞,即使有數(shù)據(jù)從網(wǎng)上發(fā)送過(guò)來(lái),程序無(wú)法到達(dá)"讀取對(duì)方回送的數(shù)據(jù)"處,程序?qū)⒉荒苁盏絼e處先主動(dòng)發(fā)送過(guò)來(lái)的數(shù)據(jù)
線(xiàn)程安全就是當(dāng)多個(gè)線(xiàn)程訪(fǎng)問(wèn)一個(gè)對(duì)象時(shí),如果不用考慮這些線(xiàn)程在運(yùn)行時(shí)環(huán)境下的調(diào)度和交替執(zhí)行,也不需要進(jìn)行額外的同步,或者在調(diào)用方進(jìn)行任何其他的協(xié)調(diào)操作,調(diào)用這個(gè)對(duì)象的行為都可以獲得正確的結(jié)果,那這個(gè)對(duì)象是線(xiàn)程安全的。
?所謂代碼塊是指用“{}”括起來(lái)的一段代碼,根據(jù)其位置和聲明的不同,可以分為普通代碼塊、構(gòu)造塊、靜態(tài)塊、和同步代碼塊。
?如果在代碼塊前加上 synchronized關(guān)鍵字,則此代碼塊就成為同步代碼塊。
同步函數(shù):當(dāng)一個(gè)函數(shù)是同步執(zhí)行時(shí),那么當(dāng)該函數(shù)被調(diào)用時(shí)不會(huì)立即返回,直到該函數(shù)所要做的事情全都做完了才返回。
死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。此時(shí)稱(chēng)系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱(chēng)為死鎖進(jìn)程。
死鎖的發(fā)生必須具備以下四個(gè)必要條件
①互斥條件:指進(jìn)程對(duì)所分配到的資源進(jìn)行排它性使用,即在一段時(shí)間內(nèi)某資源只由一個(gè)進(jìn)程占用。如果此時(shí)還有其它進(jìn)程請(qǐng)求資源,則請(qǐng)求者只能等待,直至占有資源的進(jìn)程用畢釋放。
②請(qǐng)求和保持條件:指進(jìn)程已經(jīng)保持至少一個(gè)資源,但又提出了新的資源請(qǐng)求,而該資源已被其它進(jìn)程占有,此時(shí)請(qǐng)求進(jìn)程阻塞,但又對(duì)自己已獲得的其它資源保持不放。
③不剝奪條件:指進(jìn)程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時(shí)由自己釋放。
④環(huán)路等待條件:指在發(fā)生死鎖時(shí),必然存在一個(gè)進(jìn)程——資源的環(huán)形鏈,即進(jìn)程集合{P0,P1,P2,···,Pn}中的P0正在等待一個(gè)P1占用的資源;P1正在等待P2占用的資源,……,Pn正在等待已被P0占用的資源。
?wait:告訴當(dāng)前線(xiàn)程放棄監(jiān)視器并進(jìn)入睡眠狀態(tài)直到其他線(xiàn)程進(jìn)入同一監(jiān)視器并調(diào)用notify為止
?notify:喚醒同一對(duì)象監(jiān)視器中調(diào)用wait的第一個(gè)線(xiàn)程,并于類(lèi)似飯館有一個(gè)空位后通知所有等候就餐的顧客中的第一位可以入座的情況
?notifyAll:喚醒同一對(duì)象監(jiān)視器中調(diào)用wait的所有線(xiàn)程,具有最高優(yōu)先級(jí)的線(xiàn)程首先被喚醒并執(zhí)行。用于類(lèi)似某個(gè)不定期的培訓(xùn)班終于招生滿(mǎn)額后,通知所有學(xué)員都來(lái)上課的情況
先通過(guò)start()產(chǎn)生一個(gè)線(xiàn)程對(duì)象,這時(shí)線(xiàn)程并不是正真的執(zhí)行,而是會(huì)進(jìn)入Runnable()狀態(tài),然后由Scheduler(調(diào)度器/操作系統(tǒng))來(lái)調(diào)度,正真開(kāi)始執(zhí)行的線(xiàn)程進(jìn)入了Running()狀態(tài),如果這時(shí)run中的方法結(jié)束,線(xiàn)程就結(jié)束了;如果在線(xiàn)程運(yùn)行的過(guò)程中,遇到了synchronized方法,就會(huì)發(fā)生堵塞,會(huì)在鎖中發(fā)生停滯,直到得到對(duì)象的鎖旗標(biāo)之后,重新進(jìn)入Runnable()狀態(tài)(可執(zhí)行狀態(tài)),然后由調(diào)度器統(tǒng)一執(zhí)行;如果得到wait()之后,會(huì)釋放鎖旗標(biāo),進(jìn)入wait()的等待池中,遇到nitify()就會(huì)進(jìn)入監(jiān)視器的等待池中,直到得到對(duì)象的鎖旗標(biāo)之后,重新進(jìn)入Runnable()狀態(tài)(可執(zhí)行狀態(tài)),然后由調(diào)度器統(tǒng)一執(zhí)行。
就是JDK中提供各種Java類(lèi),例如:Systom類(lèi)
?String類(lèi)對(duì)象中的內(nèi)容,一旦被初始化就不能再改變
?String類(lèi)使用final修飾,所以不能被繼承
?String的內(nèi)存結(jié)構(gòu)很特殊,在內(nèi)存中有個(gè)字符串常量池,所有的字符串存放在字符串常量池中
?StringBuffer類(lèi)用于封裝內(nèi)容可以改變的字符串
區(qū)別:
String:不可變字符串;頻繁操作時(shí),每次都需新開(kāi)辟內(nèi)存,極易造成內(nèi)存浪費(fèi)
StringBuffer:可變字符串、效率低、線(xiàn)程安全;執(zhí)行速度慢
StringBuilder:可變字符串、效率高、線(xiàn)程不安全;執(zhí)行速度快
(1)如果要操作少量的數(shù)據(jù)用 String;
(2)多線(xiàn)程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) StringBuffer;
(3)單線(xiàn)程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) StringBuilder(推薦使用)。
?StringBuffer和StringBuilder類(lèi)的對(duì)象能夠被多次的修改,并且不產(chǎn)生新的未使用對(duì)象。
?StringBuilder類(lèi)在Java5中被提出,它和StringBuffer之間的最大不同在于StringBuilder的方法不是線(xiàn)程安全的(不能同步訪(fǎng)問(wèn))。
?由于StringBuilder相較于StringBuffer有速度優(yōu)勢(shì),所以多數(shù)情況下建議使用StringBuilder類(lèi)。
?然而在應(yīng)用程序要求線(xiàn)程安全的情況下,則必須使用StringBuffer類(lèi)。
構(gòu)造方法:
?String(byte[] bytes, int offset, int length) 通過(guò)使用平臺(tái)的默認(rèn)字符集解碼指定的 byte 子數(shù)組,構(gòu)造一個(gè)新的 String
?equals 判斷內(nèi)容是否相等,區(qū)分大小寫(xiě)
?equalsIgnoreCase 判斷內(nèi)容是否相等,不區(qū)分大小寫(xiě)
?contains 是否包含子字符串
?isEmpty 判斷字符串長(zhǎng)度是否為0
?startsWith 判斷是否以該字符串為前綴
?endsWith 判斷是否以該字符串為后綴
?indexOf 判斷int值對(duì)應(yīng)的字符在該字符串中出現(xiàn)的位置||判斷子字符串在該字符串中出現(xiàn)的位置
?copyValueOf 將字符數(shù)組轉(zhuǎn)換成字符串,可以從off開(kāi)始,到length結(jié)束
?lastIndexOf 獲取最后一個(gè)字符的位置
?subString 截取
?getBytes 轉(zhuǎn)換為byte[]數(shù)組
?tocharArray 轉(zhuǎn)換成字符數(shù)組
?valueOf 將基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換成字符串,byte數(shù)組或char數(shù)組也可以
?toLowerCase 轉(zhuǎn)換成小寫(xiě)
?toUpperCase 轉(zhuǎn)換成大寫(xiě)
?concat 拼接
| 基本數(shù)據(jù)類(lèi)型 | 基本類(lèi)型的包裝類(lèi) |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
4.集合類(lèi)
?集合類(lèi)用于儲(chǔ)存一組對(duì)象,其中的每個(gè)對(duì)象稱(chēng)之為元素,經(jīng)常會(huì)用到的有Vector ,Enumeration,Arraylist,Collection ,Set,List,Iterator的集合類(lèi)和接口
?可將Java集合框架大致可分為Set、List、Queue 和Map四種體系
Set:代表無(wú)序、不可重復(fù)的集合,常見(jiàn)的類(lèi)如HashSet、TreeSet
List:代表有序、可重復(fù)的集合,常見(jiàn)的類(lèi)如動(dòng)態(tài)數(shù)組ArrayList、雙向鏈表LinkedList、可變數(shù)組Vector
Map:代表具有映射關(guān)系的集合,常見(jiàn)的類(lèi)如HashMap、LinkedHashMap、TreeMap
Queue:代表一種隊(duì)列集合
5.Properties類(lèi)
?Properties類(lèi)是Hashtable的子類(lèi)
?增加了將Hashtable對(duì)象中的關(guān)鍵字和值保存到文件中和從文件中讀取關(guān)鍵字和值到Hashtable對(duì)象中的方法
?如果要用Properties.store方法存儲(chǔ)Properties對(duì)象中的內(nèi)容,每個(gè)屬性的關(guān)鍵字和值,都必須是String類(lèi)型
6.時(shí)間和日期
SimpleDateFormat最常用幾個(gè)類(lèi):Date、DateFormat和Calendar
Calendar類(lèi):?Calendar.add()方法
?Calendar.get()方法
?Calendar.set()方法
?Calendar.getInstance靜態(tài)方法,獲取日歷對(duì)象
//格式化日期的
//pattern:日期的格式
//年(year):y表示,一般兩位或者四位
//月(month):M表示,一般2位
//日(day):d表示,一般兩位
//小時(shí)(hours):h表示,一般2位
//分鐘(minutes):m表示,一般2位
//秒(seconds):s表示,一般兩位
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
//SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd:hh:mm:ss");
return format.format(calendar.getTime());
7.Time與TimeTask類(lèi)
?schedule方法主要有如下幾種重載形式:
schedule(TimeTask task,long delay)
schedule(TimeTask task,Date time)
schedule(TimeTask task,long delay,long period)
?TimeTask類(lèi)實(shí)現(xiàn)了Runable接口,要執(zhí)行的任務(wù)由他里面實(shí)現(xiàn)的run方法來(lái)完成