Head First Java學習筆記
1.基本概念
1.1.工作方式
源代碼(.java)---編譯器(執行javac程序)---產生字節碼(.class與平臺無關)---JAVA虛擬機(JVM,讀取與執行字節碼)
1.2.匯編語言是對基礎機器的少量抽象,C,BASIC,FORTRAN等是對匯編語言的一種抽象
1.3.類實例化的過程相當於創建了一個句柄
1.4.doStuff(c),一個圓句柄傳遞給一個本來期待shape句柄的函數,圓是shape的子類,所以doStuff()發給shape的消息,circle也能接受,原因是編譯器編譯代碼時並不知道自己要操作的準確類型是什麽,這種情況叫多形性,實現的方法叫叫動態綁定
1.5.用戶提交的信息通過所有WEB服務器均能支持的“通用網關接口”(CGI)會傳到服務器
1.6.數據保存地:
1.6.1.寄存器
1.6.2.堆棧(RAM,保存句柄)
1.6.3.堆(RAM,保存對象)
1.6.4.靜態存儲(RAM,static)
1.6.5.常數存儲(ROM)
1.6.6.非RAM存儲(另一臺機器或磁盤,不依賴於程序是否運行)
1.7.實例變量數字默認值為0,BOOLEAN初始值為false,對象引用為null,局部變量沒有默認值,必須初始化
2.構造器與垃圾收集器
2.1.正在執行的方法位於棧頂,執行完被釋放掉
2.2.對象存在於堆中,實例變量存在於所屬對象中,局部變量和方法的參數的生命周期只限於方法被放在棧上的這段期間,即所有局部變量存在於棧上的堆棧塊中
2.3.primitive主數據類型變量指boolean, char, byte,short,int,long,float,double這8種
2.4.對象引用變量與primitive主數據類型變量都是放在棧上
2.5.方法的參數傳遞都是值傳遞,基本類型傳值,引用類型傳地址
2.6.內存分兩種,堆內存和棧內存
2.7.數組和對象在沒有引用變量指向它的時候,才變成垃圾,不能再被使用,但是仍然占著內存,在隨後的一個不確定的時間被垃圾回收器釋放掉。這個也是java比較占內存的主要原因
2.8.堆和棧由JVM自帶的機制進行管理
2.8.實例變量存在於對象所屬的堆空間上,如果實例變量是個對象,則會在當前對象的堆空間中存入對象的引用變量,被引用的對象在被NEW的時候放在另一個堆空間中
2.9.內存分配策略:
靜態
堆
棧
2.10.無參構造函數是必須的(沒有建的時候系統提供,自己寫了構造函數的話則必須自寫無參構造函數)
2.11.執行NEW的指令是個重大事件,它會啟動構造函數連鎖反應,一直到Object這個類為止,創建子類,其繼承的父類也會被連鎖創建,創建對象時其構造函數被逐次放到堆棧塊,逐級調用直到最上面是Object類的構造函數
2.12.如果新建子類對象時,在子類的構造函數中沒有寫對父類構造函數的調用,則編譯器會自動幫我們加上super(),對super()的調用默認會加在第一行,自寫的話也必須保證在第一行
2.13.使用this()來從某個構造函數調用同一個類的另外一個構造函數,只能用在構造函數中,且必須是第一行語句,super()與this()不能兼得
2.14.方法運行於堆棧
2.15.局部變量在方法執行時存活,方法執行完死掉,活著的時候狀態會被保存
2.16.有3種方法可以釋放對象的引用
引用離開它的範圍,如函數中有實例化,函數執行結束後
引用被重新賦值到其他對象上
引用被重新賦值為null
對象的引用死掉後,該對象就等著垃圾處理器回收了
2.17.靜態方法直接從類調用,沒有對象的引用,抽象的類是不能被初始化的
2.18.可通過用私有的構造函數來限制非抽象類被初始化eg:Math
2.19.靜態方法不能調用非靜態的變量,因為靜態方法通過類名稱來調用,所以無法引用到該類的任何實例變量,因為靜態方法不知道堆上有哪些實例
2.20.靜態方法也不能調用非靜態方法,即使可以通過引用變量調用靜態方法,但靜態方法依然不知道是哪個對象引用所做的調用
2.21.同一類所有的實例共享一份靜態變量,即可以用靜態變量來統計某個類被創建實例的個數
2.22.靜態變量的默認值為該變量類型的默認值
2.23.JVM決定什麽時候加載類
2.24.final的類不能被繼承,final方法不能被覆蓋,final變量不能被改變值
2.25.primitive數據類型與對應的包裝類型編譯器會自動進行轉換,即某處用到某種類型都可用其對應的類型替代
3.異常處理
3.1.編譯器會核對每件事,除了RuntimeException之外
3.2.判斷某個方法可能會拋出異常的方法是看該方法有沒有throws Exception,那麽其他方法在調用該方法時就要聲明try/catchl
3.3.try/catch塊種發生異常後,try後的語句不再執行,執行完catch後整個try/catch塊後接著執行
3.4.try塊失敗---catch塊---finally塊---其余部分
try塊成功---finally---其余部分
有return指令情況下流程會跳到finally然後再回到return指令
3.5.如果可能有多個異常,就要對應多個catch塊,但通常通過聲明多個異常的父類來代替聲明多個異常
3.6.在調用可能出現異常的方法時,該方法也可以拋出異常(throws Exception),那麽這個方法從堆棧上釋放掉,異常拋給調用它的方法,如果主方法也拋出異常,最終異常會拋給JVM,JVM無法處理死掉
3.7.內部類可以使用外部所有的方法與變量,就算是私用的也可以,內部類跟正常的類沒有差別還多了特殊的存取權,在外部類可以創建內部類的實例,如果要在外部類以外的程序初始內部實例,需要:
Outer ot=new Outer();
Outer.Inner in=ot.new Inner();
3.8.如果某類可序列化,則它的子類也可序列化
3.9.被標記為trasient的變量跳過實例化,靜態類不會被序列化,序列化的類需要實現Serializable接口
3.10.序列化:鏈接(此處FileOutputStream叫做連接串流)
ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream(a.ser))
os.writeObject(one);
os.writeObject(two);
...
解序列化:鏈接,讀取的順序必須與吸入的順序相同
ObjectInputStream is=new ObjectInputStream(new FileInputStream(a.ser))
One one=(One)is.readObject();
Two two=(Two)is.readObject();
...
3.11.某類被序列化,則它的引用對象也會被序列化
3.12.緩沖區bufferedWriter
BufferedWriter bw=new BufferedWriter(new FileWriter(aFile))
bufferedWriter可以暫存一堆數據,等緩沖區滿時再寫入磁盤,這樣就減少了對磁盤的操作次數,提高了效率,因為每趟磁盤操作都比內存操作話費更多的時間,如果要強制緩沖區立即寫入,可調用bw.flush()這個方法
3.13.所有的流都是以下4個基本類的子類:
InputStream Reader
OutputStream Writer
InputStream和OutputStream及其子類處理字節流,按ASCII編碼,主要用在處理二進制數據
字符流常用於文本
4.網絡與線程
4.1.Socket連接(客戶端對服務器建立)
Socket a=new Socket(“11.1.45.234”,5000)
網頁服務器(HTTP)端口是80,HTTPS:443 這是規定的標準
4.2.每個服務器有65536個TCP端口(0-65535),0-1023都被保留給已知的特定服務
4.3.字符流與字節流通過InputStreamReader,OutputStreamWriter來關聯,實際上是通過byte[]和String來關聯
4.4.從Socket得到的輸入流為字節流
4.5.PrintWriter可作為字符數據與字節間的轉換橋梁
4.6.服務器對特定端口創建:
ServerSocket serverSock=new ServerSocket(4242);
服務器會監聽4242這個端口
客戶端創建
服務器創建與客戶端通信的新Socket
A.Socket sock=serverSock.accept(); (方法在用戶連接時返回Socket)
服務器會無限循環,每次循環會調用A方法,A檢測到客戶端連接了才會繼續往下執行
4.7.JAVA.LANG是被默認導入的
4.8.JAVA虛擬機會負責主線程的啟動以及垃圾收集所需的系統用線程
4.9.只有多處理器才能同時處理好幾件事
4.10.線程調用start()方法後,進入待執行狀態,由虛擬機的線程調度機制來決定線程的狀態
4.11. GUI:圖形用戶接口
4.12.創建新線程(2中方法)
A:實現Runnable接口
Runnable r=new MyRunnable();
Thread t=new Thread(r);
T.start();
B:用線程的子類覆蓋掉run()方法
Class A extends Thread{
@Override
Void run(){......}
}
A a=new A(...)
A.start();
4.13.Thread.sleep()可以強制線程進入等待狀態直到過了設定時間為止,sleep()(可能跑出異常)可以讓所有線程都有機會運行
4.14.使用synchronized關鍵詞可以防止兩個線程同時進入同一對象的同一方法
4.15.每個對象有唯一的鎖和鑰匙,當使用同步化方法時,對象會在某個線程進入後鎖上,別的線程企圖進入就得等待
4.16.由於鎖機制,兩個線程在進入各自對象後睡覺醒來後訪問對方的對象就都得處於等待狀態,造成死鎖
4.17.類本身也有鎖,比如靜態變量的保護
4.18.通過私有的構造函數和創建靜態實例可做出單例模式
5.數據結構
5.1.對象被system.out.println()時會調用toString()方法
5.2.幾乎所有以泛型寫的程序都與處理集合有關
5.3.public <T extends Animal> void takeThing(ArrayList<T> list)
=
public void takeThing(ArrayList<? extends Animal > list)
表示任何被聲明為Animal或Animal子類的ArrayList是合法的
public static <T extends Comparable<? super T>> void sort(List<T> list)
Comparable是個接口,以泛型的觀點,extend代表extends或implements
5.4.hashCode()使用雜湊算法對heap上的對象產生獨特的值,不同的對象有可能產生相同的值
6.包,jar存檔文件和部署
6.1.javac -d 目標目錄 源文件(.java)
可生成class文件到指定目錄
6.2.jar工具可以從命令欄創建和執行JAR
7.分布式計算
7.1.目前接觸的大部分方法都是對運行在相同JAVA虛擬機的對象進行的,即調用方與被調用方在同一個堆上
7.2.JAVA遠程程序調用RMI(Remote Method Invocation)
7.3.遠程方法的參數必須是primitive或serializable類型,任何遠程方法的參數和返回值都會被打包通過網絡傳送,這是通過序列化完成的
7.4.遠程接口要繼承Remote且要聲明異常,遠程實現要繼承UnicastRemote和實現遠程接口(最簡單的方式),產生stub和skeleton文件,啟動遠程服務,遠程服務對象必須要向
RMI registry註冊,Naming.rebind()綁定
7.5.客戶端以Naming.lookup()查詢遠程服務
7.6.一般的servlet是繼承httpServlet的類並覆蓋掉doGet(),doPost()方法
7.7.WEB服務器會根據用戶請求來啟動並調用servlet上對應的方法,servlet可通過doGet()的響應參數取得輸出串流來組成響應的網頁
7.8.servlet是寫出帶有HTML輸出的類,JSP是寫出帶有JAVA程序的網頁,WEB服務器最終會把JSP轉換成servlet,如果用servlet會出現一堆難以閱讀的print命令
7.9.String s=”0”;
For(int i=1;i<10;i++){
s=s+i;
}
最後會建立10個String,建立行的String時,會被放入String pool中,不受垃圾收集器管理,浪費內存
7.10.IDE:集成開發環境
7.11.需要外部類的實例才能取得內部類的實例
7.12.傳參的時候可以直接傳類的定義
Head First Java學習筆記