Java读书笔记05 类与对象
本文為java中對(duì)象與類(lèi)等的基本知識(shí),包括方法、構(gòu)造、析構(gòu)、靜態(tài)域、初始化、包、路徑等。
對(duì)象與對(duì)象變量
在Java中,任何對(duì)象變量的值都是對(duì)存儲(chǔ)在另外一處的一個(gè)對(duì)象的引用。new操作符的返回值也是一個(gè)引用。
可以把Java中的數(shù)據(jù)類(lèi)型分為兩類(lèi),一類(lèi)是基本數(shù)據(jù)類(lèi)型,即前面提到的8種基本數(shù)據(jù)類(lèi)型(4種整型,2種實(shí)數(shù),1種字符,1種布爾);另一類(lèi)是引用類(lèi)型(reference type)。
下列語(yǔ)句:
Date deadline = new Date();
有兩個(gè)部分。表達(dá)式new Date()構(gòu)造了一個(gè)Date類(lèi)型的對(duì)象,并且它的值是對(duì)新創(chuàng)建對(duì)象的引用,這個(gè)引用被存儲(chǔ)在變量deadline中。
可以顯示地將對(duì)象變量設(shè)置為空(null)
應(yīng)該將Java的對(duì)象變量看作是C++的對(duì)象指針。
引用類(lèi)型是用在對(duì)象上的,一個(gè)對(duì)象可以被多個(gè)引用所指向,但同一時(shí)刻,每個(gè)引用只能指向唯一的一個(gè)對(duì)象。如果一個(gè)對(duì)象被多個(gè)引用所指向,那么無(wú)論哪個(gè)引用對(duì)對(duì)象屬性進(jìn)行了修改,都會(huì)反映到其他的引用當(dāng)中。
C++中沒(méi)有空引用,并且引用不能被賦值。
所有的Java對(duì)象都存儲(chǔ)在堆中。變量包含的是指向堆對(duì)象的指針。引用存放的是對(duì)象的地址。
在Java中使用clone方法來(lái)獲得對(duì)象的完整拷貝。
?
用戶(hù)自定義類(lèi)
在一個(gè)源文件中,只能有一個(gè)公有類(lèi),但可以有任意數(shù)目的非公有類(lèi)。
源文件名必須與公有類(lèi)的名字相匹配。
當(dāng)編譯源程序時(shí)所有使用到的類(lèi)都會(huì)被編譯。
?
方法
Java中所有的方法都必須在類(lèi)的內(nèi)部定義,但并不像C++那樣把類(lèi)內(nèi)部定義的方法作為inline,是否將某個(gè)方法作為內(nèi)聯(lián)方法是Java虛擬機(jī)的任務(wù)。
若需要返回一個(gè)可變數(shù)據(jù)域的拷貝,就應(yīng)該使用clone。
?
構(gòu)造器
構(gòu)造器即構(gòu)造函數(shù),工作方式與C++基本相同。但是所有的Java對(duì)象都是在堆中構(gòu)造的,構(gòu)造器總是伴隨著new操作符一起使用。
如果在編寫(xiě)一個(gè)類(lèi)時(shí)沒(méi)有編寫(xiě)構(gòu)造器,系統(tǒng)就會(huì)提供一個(gè)默認(rèn)構(gòu)造器(默認(rèn)構(gòu)造器是指沒(méi)有參數(shù)的構(gòu)造器)。系統(tǒng)提供的這個(gè)默認(rèn)構(gòu)造器會(huì)將所有的實(shí)例域設(shè)置為默認(rèn)值。
如果類(lèi)中至少提供了一個(gè)構(gòu)造器,但是沒(méi)有提供默認(rèn)的構(gòu)造器,那么在構(gòu)造對(duì)象時(shí)若不提供構(gòu)造參數(shù)就視為不合法。用戶(hù)如果希望不提供參數(shù)時(shí),所有域擁有默認(rèn)的值,可以提供一個(gè)空的默認(rèn)構(gòu)造器。
如果構(gòu)造器的第一個(gè)語(yǔ)句形如this(…),那么這個(gè)構(gòu)造器將調(diào)用同一個(gè)類(lèi)的另一個(gè)構(gòu)造器。
注意:在C++中一個(gè)構(gòu)造器不能調(diào)用另一個(gè)構(gòu)造器,必須將抽取出的公共初始化代碼編寫(xiě)成一個(gè)獨(dú)立的方法。
?
方法參數(shù)
?
隱式參數(shù)與顯式參數(shù)
每一個(gè)方法中,this表示隱式參數(shù),表示對(duì)象。
顯式參數(shù)是列在方法括號(hào)中的數(shù)值。
?
方法參數(shù)的傳遞
C++有值調(diào)用和引用調(diào)用,引用參數(shù)標(biāo)有&符號(hào)。
Java程序設(shè)計(jì)語(yǔ)言使用值調(diào)用,方法得到的是參數(shù)值的一個(gè)拷貝。
即對(duì)于Java中的方法參數(shù)傳遞,無(wú)論傳遞的是原生數(shù)據(jù)類(lèi)型,還是引用類(lèi)型,統(tǒng)一是傳值(pass by value)。
對(duì)于基本數(shù)據(jù)類(lèi)型來(lái)說(shuō),方法中的變量被初始化為實(shí)參的一個(gè)拷貝,方法結(jié)束后,原來(lái)的在方法外部的變量并不改變,而方法中的變量不再使用。
對(duì)于對(duì)象引用來(lái)說(shuō),方法中的變量被初始化為對(duì)象引用值的拷貝,即一個(gè)對(duì)象的引用。方法可以改變一個(gè)對(duì)象參數(shù)的狀態(tài)。
但是認(rèn)為Java對(duì)對(duì)象采用的是引用調(diào)用,這種理解是不對(duì)的。如果將兩個(gè)對(duì)象的引用的拷貝在方法中交換,這樣并不能夠真的交換這兩個(gè)對(duì)象。這說(shuō)明一個(gè)方法不能讓對(duì)象參數(shù)引用一個(gè)新的對(duì)象。
?
靜態(tài)域與靜態(tài)方法
?
靜態(tài)域:
如果將域定義為static,那么每個(gè)類(lèi)中只有一個(gè)這樣的域。而每一個(gè)對(duì)象對(duì)于所有的實(shí)例域卻都有一份自己的拷貝。
?
靜態(tài)常量:
public static final double PI=3.1415926535;
public static final PrintStream out=…;
?
靜態(tài)方法:
靜態(tài)方法是不能向?qū)ο髮?shí)施操作的方法。即沒(méi)有隱式的參數(shù)this。
main方法是一個(gè)靜態(tài)方法,因?yàn)樵趩?dòng)程序的時(shí)候還沒(méi)有任何一個(gè)對(duì)象。
(每個(gè)類(lèi)可以有個(gè)main方法,這是對(duì)類(lèi)進(jìn)行單元測(cè)試時(shí)一個(gè)常用技巧。)
因?yàn)殪o態(tài)方法不能操作對(duì)象,所以不能在靜態(tài)方法中訪(fǎng)問(wèn)實(shí)例域。但是靜態(tài)方法可以訪(fǎng)問(wèn)自身類(lèi)中的靜態(tài)域。
以下兩種情況使用靜態(tài)方法:
1.當(dāng)一個(gè)方法不需要訪(fǎng)問(wèn)對(duì)象狀態(tài),所有參數(shù)都是通過(guò)顯示參數(shù)提供的。
2.當(dāng)一個(gè)方法只需要訪(fǎng)問(wèn)類(lèi)的靜態(tài)域。
?
顯式域初始化
在執(zhí)行構(gòu)造器之前先進(jìn)行賦值,當(dāng)一個(gè)類(lèi)的所有構(gòu)造器都希望將相同的值賦予某個(gè)特定的實(shí)例域時(shí),這種方法特別有用。
初始值不一定是常量,域可以調(diào)用方法來(lái)進(jìn)行初始化。
?
靜態(tài)初始化:
對(duì)靜態(tài)域進(jìn)行初始化可以將代碼放在一個(gè)塊中,并標(biāo)記關(guān)鍵字static。在類(lèi)第一次加載的時(shí)候,將會(huì)進(jìn)行靜態(tài)域的初始化,與實(shí)例域一樣,靜態(tài)域的默認(rèn)初始值為false或null,除非將它們顯式設(shè)置成其他值。
所有的靜態(tài)初始化語(yǔ)句以及靜態(tài)初始化塊 都將按照類(lèi)定義中出現(xiàn)的順序執(zhí)行。
?
對(duì)象析構(gòu)與finalize方法
Java有自動(dòng)的垃圾回收器,不需要人工回收內(nèi)存,所以不支持析構(gòu)器。
當(dāng)使用了內(nèi)存之外的其他資源,如文件或使用了系統(tǒng)資源的另一個(gè)對(duì)象的句柄,在這種情況下,當(dāng)資源不再需要的時(shí)候,將其回收和再利用十分重要。
可以為任何一個(gè)類(lèi)添加finalize方法,該方法將在垃圾回收器清除對(duì)象之前被調(diào)用。在實(shí)際應(yīng)用中,不要使用finalize方法回收任何短缺的資源,這是因?yàn)楹茈y知道這個(gè)方法什么時(shí)候才能夠被調(diào)用。
如果某個(gè)資源需要在使用完畢后立刻被關(guān)閉,就需要人工管理。提供一個(gè)類(lèi)似dispose或close這樣的方法,用來(lái)做相應(yīng)的清理。如果一個(gè)類(lèi)使用了這樣的方法,當(dāng)對(duì)象不再使用時(shí)一定要調(diào)用它。
?
包
package將類(lèi)組織起來(lái)。
所有標(biāo)準(zhǔn)的Java包都處于java和javax包層次中。
使用包的主要原因是確保類(lèi)名的唯一性,Sun公司建議將公司的英特網(wǎng)域名以逆序的形式作為包名,并且對(duì)于不同的項(xiàng)目使用不同的子包。
包嵌套的唯一目的是管理唯一的名字。從編譯器的角度來(lái)看,嵌套的包之間沒(méi)有任何關(guān)系。每一個(gè)都擁有獨(dú)立的類(lèi)集合。
?
類(lèi)的導(dǎo)入
一個(gè)類(lèi)可以使用所屬包中的所有類(lèi),以及其他包中的公有類(lèi)。
訪(fǎng)問(wèn)另一個(gè)包中的共有類(lèi)有兩種方式:
1.在每個(gè)類(lèi)名之前添加完整的包名。如:
java.util.Date today = new java.util.Date();
2.使用import語(yǔ)句(位于源文件頂部,package語(yǔ)句的后面)導(dǎo)入一個(gè)特定的類(lèi)或者整個(gè)包。如:
import java.util.*;
還可以導(dǎo)入一個(gè)包中的特定類(lèi):
import java.util.Date;
?
靜態(tài)導(dǎo)入
import語(yǔ)句不僅可以導(dǎo)入類(lèi),還增加了導(dǎo)入靜態(tài)方法和靜態(tài)域的功能。
import static java.lang.System.*;
?
將類(lèi)放入包中
要想將一個(gè)類(lèi)放入包中,就必須將包的名字放在源文件的開(kāi)頭。如:
package com.horstmann.corejava;
如果沒(méi)有在源文件中放置package語(yǔ)句,那么這個(gè)源文件中的類(lèi)就被放置在一個(gè)默認(rèn)包中,默認(rèn)包是一個(gè)沒(méi)有名字的包。
?
虛擬機(jī)如何定位類(lèi)
類(lèi)存儲(chǔ)在文件系統(tǒng)的子目錄中,類(lèi)的路徑必須與包名匹配。
另外,還可以利用JAR實(shí)用程序?qū)㈩?lèi)文件添加到歸檔文件中。在一個(gè)歸檔文件中,可以包含多個(gè)類(lèi)文件和子目錄,這樣既可以節(jié)省又可以改善性能。
類(lèi)路徑所列出的目錄和歸檔文件是搜尋類(lèi)的起始點(diǎn),是所有基目錄的集合,基目錄中的子目錄可以用于包含類(lèi)文件。
設(shè)置類(lèi)路徑的方法取決于編譯環(huán)境。如果使用JDK,那么就有兩種選擇:為編譯器和字節(jié)碼解釋器指定-classpath選項(xiàng),或者設(shè)置CLASSPATH環(huán)境變量。
具體的設(shè)置細(xì)節(jié)取決于操作系統(tǒng)。
句點(diǎn).表示當(dāng)前目錄,Windows環(huán)境中,各基目錄以分號(hào);間隔。
由于運(yùn)行時(shí)庫(kù)文件(在jre/lib與jre/lib/ext目錄下的rt.jar和一些其他的JAR文件)會(huì)被自動(dòng)地搜索,所以不必將它們顯式地列在類(lèi)路徑中。
為編譯器設(shè)置類(lèi)路徑:
javac –classpath …
也可以用-cp代替-classpath
javac編譯器總是在當(dāng)前目錄中查找文件,而java解釋器僅在類(lèi)路徑中有.目錄的時(shí)候,才查看當(dāng)前目錄。
?
包作用域
標(biāo)記為public的部分可以被任意的類(lèi)使用;
標(biāo)記為private的部分只能被定義它們的類(lèi)使用。
如果沒(méi)有指定public或private,那么這個(gè)部分可以被同一個(gè)包中的所有方法訪(fǎng)問(wèn)。
總結(jié)
以上是生活随笔為你收集整理的Java读书笔记05 类与对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Linux中压缩、解压缩(tar/zip
- 下一篇: Java编程中写出好代码的建议