摘要:所以,在讀的核心技術(shù)的過(guò)程中,我記錄下這些所謂的易忽略的問(wèn)題,這些問(wèn)題將會(huì)持續(xù)更新在我的這個(gè)的博客下,也算是激勵(lì)自己重新挖掘這些基礎(chǔ)問(wèn)題的內(nèi)涵。類路徑只是讓能夠通過(guò)配置好的全路徑名找到所需的外部類。
開(kāi)篇
Java是一門不那么簡(jiǎn)單也不那么復(fù)雜的語(yǔ)言,Java里面有很多問(wèn)題和特性是容易被使用者忽視的,這些問(wèn)題也許會(huì)難住新手,同時(shí)也許會(huì)是老手不小心跌入的無(wú)故之坑,只有精于對(duì)基礎(chǔ)的提煉才能最大程度地解決類似的疑問(wèn)。所以,在讀Cay.Horstmann的《Java核心技術(shù)》的過(guò)程中,我記錄下這些所謂的易忽略的問(wèn)題,這些問(wèn)題將會(huì)持續(xù)更新在我的這個(gè)Segment Fault的博客下,也算是激勵(lì)自己重新挖掘這些基礎(chǔ)問(wèn)題的內(nèi)涵。這個(gè)博客將以原書(shū)中的章節(jié)為分割,大概會(huì)是每章一篇,持續(xù)更新,每篇的內(nèi)容也不會(huì)一次全部寫完,視我個(gè)人對(duì)問(wèn)題的理解和我的閱讀進(jìn)度而定。
另外,我們從本書(shū)第一卷第四章開(kāi)始,因?yàn)榍叭聼o(wú)外乎就是在講述歷史和環(huán)境配置,我認(rèn)為和我們的主題不大相關(guān)。
Core Java Volume 1 chap4 java類和包的訪問(wèn)權(quán)限public,private等這些訪問(wèn)控制標(biāo)識(shí)對(duì)java的類和包來(lái)說(shuō)都是可用的,而且在類中的屬性和方法、包中的方法來(lái)說(shuō)訪問(wèn)權(quán)限上的定義也是共通的:
public屬性和方法:這些方法的訪問(wèn)權(quán)限是公開(kāi)的,也就是說(shuō)所有的類內(nèi)部和外部對(duì)象都可以訪問(wèn)這些公開(kāi)的屬性和方法;
public類:這些類的訪問(wèn)權(quán)限是公開(kāi)的,也就是說(shuō)在包內(nèi)的類和包外的類都可以訪問(wèn)這些公開(kāi)的類;
private屬性和方法:這些方法是類私有的,也就是說(shuō)只能被類內(nèi)部所訪問(wèn);
private類:這些類的訪問(wèn)權(quán)限是私有的,也就是說(shuō)只能被包內(nèi)部所訪問(wèn)。
究竟什么是CLASSPATH顧名思義,classpath指的是類路徑,也就是jvm在搜尋class二進(jìn)制文件時(shí)搜尋的目錄,在這個(gè)目錄中如果找到需要的class文件則去執(zhí)行,我們可以通過(guò)執(zhí)行前為java命令設(shè)置-classpath參數(shù)或者直接設(shè)置CLASSPATH系統(tǒng)環(huán)境變量的形式去定義這個(gè)類路徑,jvm就會(huì)去這個(gè)指定的路徑下搜尋需要的class文件。
這個(gè)例子說(shuō)明這個(gè)問(wèn)題:
我們可以在系統(tǒng)環(huán)境變量配置文件中這樣配置java的CLASSPATH:
export CLASSPATH=".:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"
這樣的配置文件等同于在java命令中的 -classpath參數(shù):
java -classpath .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar Test
這樣配置CLASSPATH環(huán)境變量或使用-classpath參數(shù)之后,jvm在尋找程序中使用的不包含在當(dāng)前類中的類時(shí)就會(huì)去這些路徑下尋找,比如說(shuō)程序中使用了不包含在當(dāng)前類中的com.rocking.People類(People類通過(guò)importcom.rocking.*引入的),那么就會(huì)依照類路徑中指示的路徑去尋找:
壓縮入$JAVA_HOME/lib/dt.jar中的com/rocking/People.class(jdk提供的系統(tǒng)級(jí)jar包)
壓縮入$JAVA_HOME/lib/tools.jar的com/rocking/People.class
./com/rocking/People.class(當(dāng)前路徑.拼接上class的全路徑名)
package com.rocking; public class People{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } import com.rocking.People; public class Test { public static void main(String[] args) { People people = new People(); } }
最重要的一點(diǎn)是,我們上面的討論都是在jvm尋找class文件的過(guò)程中,而非javac編譯器尋找待編譯的java source文件的過(guò)程中,在編譯中,我們必須通過(guò)package定義當(dāng)前類所在的包(或者不明確定義直接使用default package),需要導(dǎo)入外部類時(shí)import相應(yīng)包,只有這樣才能通過(guò)編譯。類路徑只是讓jvm能夠通過(guò)配置好的全路徑名找到所需的外部類。
setter的不可靠性理論上我們將域?qū)傩栽O(shè)置為private的目的是為了不讓程序能夠輕易地訪問(wèn)和修改到這個(gè)對(duì)象私有的屬性,而只能通過(guò)該類定義的public的getter和setter方法去訪問(wèn)和修改。但是這并不是完全可靠的,程序仍然可以通過(guò)一些靈巧的辦法在某些合適的情況下獲取和更改這些私有的屬性值。
setter的不可靠性,其實(shí)只要能夠確定這個(gè)私有屬性的引用,是完全可以直接做更改的,當(dāng)然前提是獲取到這個(gè)引用,比如通過(guò)getter拿到這個(gè)屬性的引用。這是一個(gè)例子:
class Secret{ private StringBuffer secret = new StringBuffer("A Secret"); public StringBuffer getSecret() { return secret; } public void setSecret(StringBuffer secret) { this.secret = secret; } } public class TestClass { public static void main(String[] args) { Secret secret = new Secret(); StringBuffer saidSecret = secret.getSecret(); saidSecret.append(":broken"); System.out.println(secret.getSecret()); } }
當(dāng)然。這個(gè)例子其實(shí)是個(gè)特例,因?yàn)槲覀儷@取到的私有屬性的引用是StringBuffer類型,是可修改內(nèi)容的引用,但是如果是String類型的secret,那么我們就沒(méi)辦法這樣繞過(guò)setter去修改了,因?yàn)镾tring類型的引用是不允許修改原值的。
private的訪問(wèn)權(quán)限我們都知道的是private屬性是私有的,那么到底是對(duì)象私有的還是類私有的呢?答案是后者,我們可以在類定義的內(nèi)部訪問(wèn)私有屬性,即使這個(gè)屬性是其他對(duì)象的,只要是同類的即可,雖然我們很少這么使用,但是這卻深刻地說(shuō)明java中的訪問(wèn)權(quán)限在類的范疇上。下面說(shuō)明了這樣一個(gè)問(wèn)題:
class Secret { private String secret; public String getSecret() { return secret; } public void setSecret(String secret) { this.secret = secret; } public void readOtherSecret(Secret otherSecret) { System.out.println(otherSecret.secret); } } public class TestClass { public static void main(String[] args) { Secret secret1 = new Secret(); secret1.setSecret("secret A"); Secret secret2 = new Secret(); secret2.setSecret("secret B"); secret1.readOtherSecret(secret2); secret2.readOtherSecret(secret1); } }static究竟是什么意思
static的本意是靜態(tài)的,在java里面這個(gè)靜態(tài)的意思是指存在于靜態(tài)的類中的,而非程序開(kāi)跑之后運(yùn)行時(shí)的動(dòng)態(tài)對(duì)象的,所以static的域?qū)傩砸埠?,方法也好,都是指那些存在于類中的域?qū)傩院头椒ǎm然該類對(duì)應(yīng)的對(duì)象中也存在static域?qū)傩院头椒ǖ目截?,但是屬于類的,?duì)于它們的影響將會(huì)影響到整個(gè)類,換言之這些影響將會(huì)產(chǎn)生在所有的類對(duì)象中。
static的方法只能訪問(wèn)static的域?qū)傩裕@個(gè)是怎么來(lái)的呢?其實(shí)就是因?yàn)閟tatic屬性是屬于整個(gè)類的,所以static的方法就不應(yīng)該影響特定的對(duì)象的屬性,在實(shí)現(xiàn)上說(shuō)這個(gè)方法的隱式參數(shù)是不含有非static的方法的指向當(dāng)前對(duì)象的this引用的,因此不能在static方法中訪問(wèn)非static屬性。
在C++中被反復(fù)向初學(xué)者討論的一個(gè)問(wèn)題就是swap函數(shù)的效果,如果參數(shù)是值傳遞的,則最終傳入的兩個(gè)值是不會(huì)被交換的,如果是指針(引用)傳遞的,那么最終傳入的兩個(gè)引用是會(huì)被交換的,那么java中的方法參數(shù)傳遞是哪種情況呢?答案是前者,即值傳遞,又叫做拷貝實(shí)參傳遞,即運(yùn)行在方法中的形式參數(shù)是傳遞給方法的真實(shí)參數(shù)的拷貝,而非直接傳入實(shí)際參數(shù)的指針。
下面的例子說(shuō)明了這個(gè)問(wèn)題:
class Some{ private String someThing; public String getSomeThing() { return someThing; } public void setSomeThing(String someThing) { this.someThing = someThing; } public Some(String someThing) { super(); this.someThing = someThing; } } public class TestClass { public static void swap(Some some1,Some some2){ Some temp = some1; some2 = some1; some1 = temp; } public static void main(String[] args) { Some some1 = new Some("1"); Some some2 = new Some("2"); swap(some1, some2); System.out.println(some1.getSomeThing()); System.out.println(some2.getSomeThing()); } }類和對(duì)象初始化
我們都知道的是對(duì)象的初始化會(huì)引發(fā)類的初始化,初始化實(shí)現(xiàn)的方法也很多,最一般的初始化方法用于對(duì)象創(chuàng)建時(shí)對(duì)域?qū)傩缘某跏蓟?,稍微少?jiàn)的類的靜態(tài)代碼塊用于對(duì)static靜態(tài)域?qū)傩赃M(jìn)行初始化,而初始化代碼塊則用于對(duì)象的域?qū)傩裕ò╯tatic域?qū)傩裕┻M(jìn)行初始化,那么一般而言,初始化的順序是怎樣的呢?
首先執(zhí)行靜態(tài)代碼塊初始化static類靜態(tài)域?qū)傩杂糜谠谡麄€(gè)類及其對(duì)象共享;
其次執(zhí)行初始化代碼塊初始化域?qū)傩砸酝瓿蓪?duì)對(duì)象的個(gè)性化的域?qū)傩缘某跏蓟?br>最后執(zhí)行對(duì)象的初始化方法以完成進(jìn)一步的域?qū)傩缘某跏蓟?/p>
class Some{ private String someThing; private static String staticSomeThing; static { staticSomeThing = "static"; System.out.println("static block triggered"); } { someThing = "some"; System.out.println("init block triggered"); } public String getSomeThing() { return someThing; } public void setSomeThing(String someThing) { this.someThing = someThing; } public Some(String someThing) { this.someThing = someThing; System.out.println("init method triggered"); } } public class TestClass { public static void main(String[] args) { Some some1 = new Some("1"); } }
未完成。。。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65339.html
摘要:而并不是父類對(duì)象的引用,而只是給編譯器的一個(gè)提示性質(zhì)的標(biāo)志?;蛘咦远x的提示在編譯的時(shí)候使用當(dāng)前子類的父類定義的構(gòu)造器去初始化當(dāng)前對(duì)象。所以,總結(jié)起來(lái),的用法歸為兩種一是可以調(diào)用父類構(gòu)造器,二是可以調(diào)用父類方法。 開(kāi)篇Java是一門不那么簡(jiǎn)單也不那么復(fù)雜的語(yǔ)言,Java里面有很多問(wèn)題和特性是容易被使用者忽視的,這些問(wèn)題也許會(huì)難住新手,同時(shí)也許會(huì)是老手不小心跌入的無(wú)故之坑,只有精于對(duì)基礎(chǔ)...
摘要:內(nèi)部類就是這樣一個(gè)情況,內(nèi)部類的出現(xiàn)雖然在運(yùn)行時(shí)會(huì)被拆分為獨(dú)立的臨時(shí)類,但是在代碼層面加深了對(duì)代碼的理解難度,所以很難說(shuō)其優(yōu)弊殊勝。 Core Java Volume 1 Key Points chap6 接口和抽象類的概念 接口和抽象類是Java繼承鏈的基礎(chǔ),其區(qū)別也較為明顯,在Java語(yǔ)言的設(shè)計(jì)中,允許接口的多實(shí)現(xiàn),但不允許抽象類的多繼承,這樣做符合簡(jiǎn)潔明了的面向?qū)ο笤O(shè)計(jì)思路:也就...
摘要:前言大家好,這里是從零開(kāi)始學(xué)之?dāng)?shù)據(jù)類型,本文首發(fā)于公眾號(hào),歡迎前往大家關(guān)注。輸出布爾類型中的布爾類型用表示,它的值有和。若需要可空引用時(shí),布爾類型的值會(huì)被裝箱。此時(shí)程序會(huì)拋出異常最后從零開(kāi)始學(xué)之?dāng)?shù)據(jù)類型到這里就結(jié)束了。 前言 大家好,這里是「從零開(kāi)始學(xué) Kotlin 之『2 』數(shù)據(jù)類型」,本文首發(fā)于公眾號(hào)「Binguner」,歡迎前往大家關(guān)注。我會(huì)每周分享一些關(guān)于 Android 和...
摘要:老實(shí)說(shuō),當(dāng)時(shí)一進(jìn)入世界的大門就暈了,各種規(guī)范概念和英文縮寫詞能把人整的暈暈乎乎。等新的英文縮寫又出現(xiàn)了,一口老血還沒(méi)來(lái)得及噴出,又重新振作開(kāi)始新的學(xué)習(xí)征程。 showImg(http://upload-images.jianshu.io/upload_images/1131767-1c5d16e39435df10.jpg?imageMogr2/auto-orient/strip%7Ci...
閱讀 3904·2021-09-27 13:35
閱讀 1083·2021-09-24 09:48
閱讀 2912·2021-09-22 15:42
閱讀 2353·2021-09-22 15:28
閱讀 3156·2019-08-30 15:43
閱讀 2624·2019-08-30 13:52
閱讀 2981·2019-08-29 12:48
閱讀 1460·2019-08-26 13:55