最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Java學(xué)習(xí)記錄:對(duì)象與類(二)

2023-03-19 19:26 作者:冰靈___Ling  | 我要投稿

類路徑:

類存儲(chǔ)在文件系統(tǒng)的子目錄中。類的路徑必須與包名匹配。

另外,類文件也可以存儲(chǔ)在JAR(java歸檔)文件中。在一個(gè)JAR文件中,可以包含多個(gè)壓縮格式的類文件和子目錄,這樣既可以節(jié)省空間又可以改善性能。在程序中用到第三方的庫(kù)時(shí),你通常會(huì)得到一個(gè)或多個(gè)需要包含的JAR文件。(第11章會(huì)講JAR文件)

【提示:JAR文件使用ZIP格式組織文件和子目錄??梢允褂萌魏蝂IP工具查看JAR文件?!?/p>

為了使類能夠被多個(gè)程序共享,需要做到下面幾點(diǎn):

1.?把類文件放到一個(gè)目錄中,例如/home/user/classdir。需要注意,這個(gè)目錄是包樹(shù)狀結(jié)構(gòu)的基目錄。如果希望增加com.horstmann.corejava.Employee類,那么Employee.class類文件就必須位于子目錄/home/user/classdir/com/horstmann/corejava中。

2.?將JAR文件放在一個(gè)目錄中,例如/home/user/archives。

3.?設(shè)置類路徑(class path)。類路徑是所有包含類文件的路徑的集合。

在UNIX環(huán)境中,類路徑中的各項(xiàng)之間用冒號(hào)(:)分割:

/home/user/classdir:.:/home/user/archives/archive.jar

而在Windows環(huán)境中,則以分號(hào)(;)分割:

C:\classdir;.;C:\archives\archive.jar

不論是UNIX還是Windows,都用句點(diǎn)(.)表示當(dāng)前目錄。

類路徑包括:

·基目錄/home/user/classdir或C:\classdir;

·當(dāng)前目錄(.)

·JAR文件/home/user/archives/archive.jar或者C:\archives\archive.jar.

從java6開(kāi)始,可以為JAR文件目錄指定一個(gè)通配符,如下:

/home/user/classdir:.:/home/user/archives/’*’

或者

C:\classdir;.;C:\archives\*

在UNIX中,*必須轉(zhuǎn)義以防止shell擴(kuò)展。

archives目錄中的所有JAR文件(但不包括.class文件)都包含在這個(gè)類路徑中。

由于總是會(huì)搜索JavaAPI的類,所以不必顯式地包含在類路徑中。

【警告:javac編譯器總是在當(dāng)前目錄中查找文件,但只有當(dāng)類路徑中包含“.”目錄時(shí),java虛擬機(jī)才會(huì)查看當(dāng)前目錄。如果你沒(méi)有設(shè)置類路徑,那么沒(méi)有什么問(wèn)題,因?yàn)槟J(rèn)的類路徑會(huì)包含”.“目錄。但是如果你設(shè)置了類路徑卻忘記包含”.“目錄,那么盡管你的程序可以沒(méi)有錯(cuò)誤地通過(guò)編譯,但不能運(yùn)行?!?/p>

類路徑所列出地目錄和歸檔文件是搜尋類地起始點(diǎn)。下面看一個(gè)類路徑示例:

/home/user/classdir:.:/home/user/archives/archive.jar

假定虛擬機(jī)要搜尋com.horstmann.corejava.Employee類的類文件。它首先要查看JavaAPI類,顯然,在那里找不到相應(yīng)的類文件,所以轉(zhuǎn)而查看類路徑。它會(huì)查找以下文件:

·/home/user/classdir/com/horstmann/corejava/Employee.class

·com/horstmann/corejava/Employee.class(從當(dāng)前目錄開(kāi)始)

·com/horstmann/corejava/Employee.class(/home/user/archives/archive.jar中)

編譯器查找文件要比虛擬機(jī)復(fù)雜得多。如果引用了一個(gè)類,而沒(méi)有指定這個(gè)類的包,那么編譯器將首先查找包含這個(gè)類的包。它會(huì)查看所有的import指令,確定其中是否包含這個(gè)類。例如,假定源文件包含指令:

Import java.util.*;

Import com.horstmann.corejava.*;

并且源代碼引用了Employee類。編譯器將嘗試查找java.lang.Employee(因?yàn)榭偸菚?huì)默認(rèn)導(dǎo)入java.lang包)、java.util.Employee、com.horstmann.corejava.Employee和當(dāng)前包中的Employee。它會(huì)在類路徑所有位置中搜索以上各個(gè)類。如果找到一個(gè)以上的類,就會(huì)產(chǎn)生編譯時(shí)錯(cuò)誤(因?yàn)橥耆薅惷仨毷俏ㄒ坏模詉mport語(yǔ)句的次序并不重要)。

編譯器的任務(wù)不止這些,它還要查看源文件是否比類文件新。如果是這樣的話,那么源文件就會(huì)自動(dòng)地重新編譯。在前面已經(jīng)知道,只可以導(dǎo)入其他包中的公共類。一個(gè)源文件只能包含一個(gè)公共類,并且文件名與公共類名必須匹配。因此,編譯器很容易找到公共類的源文件。不過(guò),還可以從當(dāng)前包中導(dǎo)入非公共類。這些類有可能在與類名不同的源文件中定義。如果從當(dāng)前包中導(dǎo)入一個(gè)類,那么編譯器就要搜索當(dāng)前包中的所有源文件,查看哪個(gè)源文件定義了這個(gè)類。

?

設(shè)置類路徑

最好使用-classpath(或-cp,或者Java中的--class-path)選項(xiàng)指定類路徑:

java -classpath /home/user/classdir:.:/home/user/archive.jar MyProg

或者

java -classpath c:\classdir;.;c:\archives\archive.jar MyProg

整個(gè)指令必須寫(xiě)在一行中。將這樣一個(gè)很長(zhǎng)的命令行放在一個(gè)shell腳本或一個(gè)批處理文件中是個(gè)不錯(cuò)的主意。

利用-classpath選項(xiàng)設(shè)置類路徑是首選的方法,另一種方法是通過(guò)設(shè)置CLASSPATH環(huán)境變量來(lái)指定類路徑。具體細(xì)節(jié)依賴于所使用的shell。在Bourne Again shell(bash)中,命令如下:

export CLASSPATH=/home/user/classdir:.:/home/user/archives/archive.jar

在Windows shell中,命令如下:

set CLASSPATH=c:\classdir;.;c:\archives\archive.jar

直到退出shell為止,類路徑設(shè)置均有效。

【警告:有人建議永久地設(shè)置CLASSPATH環(huán)境變量。一般來(lái)說(shuō),這是一個(gè)糟糕地想法。人們有可能會(huì)忘記全局設(shè)置,因此,當(dāng)他們的類沒(méi)有正確地加載時(shí),就會(huì)感到很奇怪。一個(gè)頗受詬病的示例是Windows中Apple QuickTime安裝程序。很多年來(lái),它都將CLASSPATH全局設(shè)置為指向它需要的一個(gè)JAR文件,而沒(méi)有在類路徑中包含當(dāng)前目錄。因此,當(dāng)程序編譯后卻不能運(yùn)行時(shí),無(wú)數(shù)JAVA程序員不得不花費(fèi)很多精力去解決這個(gè)問(wèn)題?!?/p>

【警告:過(guò)去,有人建議完全繞過(guò)類路徑,將所有的JAR文件都放在jre/lie/ext目錄中。這種機(jī)制在Java9中已經(jīng)過(guò)時(shí),不過(guò)不管怎樣這都是一個(gè)不好的建議。從擴(kuò)展目錄加載一些已經(jīng)遺忘很久的類時(shí),這會(huì)讓人非常困惑。】

【注釋:在Java9中,還可以從模塊路徑加載類。本書(shū)卷II的第9章將討論模塊和模塊路徑?!?/p>

?

JAR文件:

在將應(yīng)用程序打包時(shí),你希望只向用戶提供一個(gè)單獨(dú)的文件,而不是一個(gè)包含大量類文件的目錄結(jié)構(gòu),Java歸檔(JAR)文件就是為此目的而設(shè)計(jì)的。JAR文件既可以包含類文件,也可以包含諸如圖像和聲音等其他類型的文件。此處,JAR文件是壓縮的,它使用了我們熟悉的ZIP壓縮格式。

創(chuàng)建JAR文件:

可以使用jar工具制作JAR文件(在默認(rèn)的JDK安裝中,這個(gè)工具位于jdk/bin目錄下)。創(chuàng)建一個(gè)新JAR文件最常用的命令使用以下語(yǔ)法:

jar cvf jarFileName file1file2...

例如:

jar cvf CalculatorClasses.jar*.class icon.gif

通常,jar命令的格式如下:

jar options file1file2...

可以將應(yīng)用程序和代碼庫(kù)打包在JAR文件中。例如,如果想在一個(gè)Java程序中發(fā)送郵件,可以使用打包在文件javax.mail.jar中的一個(gè)庫(kù)。

?

以下是jar程序選項(xiàng):

用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...

選項(xiàng):

????-c ?創(chuàng)建新檔案

????-t ?列出檔案目錄

????-x ?從檔案中提取指定的 (或所有) 文件

????-u ?更新現(xiàn)有檔案

????-v ?在標(biāo)準(zhǔn)輸出中生成詳細(xì)輸出,詳細(xì)輸出告訴您每個(gè)文件添加到 JAR 文件時(shí)的名稱。

????-f ?指定檔案文件名

????-m ?包含指定清單文件中的清單信息。

????-n ?創(chuàng)建新檔案后執(zhí)行 Pack200 規(guī)范化

????-e ?為捆綁到可執(zhí)行 jar 文件的獨(dú)立應(yīng)用程序指定應(yīng)用程序入口點(diǎn)

????-0 ?(數(shù)字零)選項(xiàng)表示僅存儲(chǔ)而不使用 ZIP 壓縮 JAR 文件

????-P ?保留文件名中的前導(dǎo) '/' (絕對(duì)路徑) 和 ".." (父目錄) 組件

????-M ?指示不應(yīng)生成默認(rèn)清單文件。Jar 工具默認(rèn)會(huì)自動(dòng)將一個(gè)清單文件添加到 Jar 歸檔文件中,其路徑名為 META-INF/ manifest

????-i ?為指定的 jar 文件生成索引信息

????-C ?更改為指定的目錄并包含以下文件

如果任何文件為目錄, 則對(duì)其進(jìn)行遞歸處理。

清單文件名, 檔案文件名和入口點(diǎn)名稱的指定順序

與 'm', 'f' 和 'e' 標(biāo)記的指定順序相同。

示例 1: 將兩個(gè)類文件歸檔到一個(gè)名為 classes.jar 的檔案中:

???????jar cvf classes.jar Foo.class Bar.class

示例 2: 使用現(xiàn)有的清單文件 'mymanifest' 并

???????????將 foo/ 目錄中的所有文件歸檔到 'classes.jar' 中:

???????jar cvfm classes.jar mymanifest -C foo/ .

關(guān)于jar的常見(jiàn)用法請(qǐng)?jiān)L問(wèn):jar工具詳解 - 簡(jiǎn)書(shū) (jianshu.com)

?

清單文件:

除了類文件、圖像和其他資源外,每個(gè)JAR文件還包含一個(gè)清單文件(meanifest),用于描述歸檔文件的特殊特性。

清單文件被命名為MANIFEST.MF,它位于JAR文件的一個(gè)特殊的META.INF子目錄中。合法的最小清單文件極其簡(jiǎn)單:

Manifest-Version: 1.0

簡(jiǎn)單的清單文件可能包含更多條目。這些清單條目被分組為多個(gè)節(jié)。第一節(jié)被稱為主節(jié)(main section)。它作用于整個(gè)JAR文件。隨后的條目可以指定命名實(shí)體的屬性,如單個(gè)文件、包或者URL。它們都必須以一個(gè)Name條目開(kāi)始。節(jié)與節(jié)之間用空行分開(kāi)。例如:

Manifest-Version: 1.0
lines describing this archive

Name: Woozle.class
lines describing this file
Name: com/mycompany/mypkg/
lines describing this package

要想編輯清單文件,需要將希望添加到清單文件中的行放到文本文件中,然后運(yùn)行。

jar cfm jarFileName manifestFileName...

例如,要?jiǎng)?chuàng)建一個(gè)包含清單文件的JAR文件,應(yīng)該運(yùn)行:

java cfm MyArchive.jar manifest.mf com/mycompany/mypkg/*.class

要想更新一個(gè)已有的JAR文件的清單,則需要將增加的部分放置到一個(gè)文本文件中,然后執(zhí)行以下命令:

java ufm MyArchive.jar manifest-additions.mf

【注釋:請(qǐng)參見(jiàn)http://docs.oracle.com/javase/10/docs/specs/jar/jar.html獲得有關(guān)JAR文件和清單文件格式的更多信息?!?/p>

?

可執(zhí)行JAR文件:

可以使用jar命令中的e選項(xiàng)指定程序的入口點(diǎn),即通常調(diào)用java執(zhí)行程序時(shí)指定的類:

java cvfe Myprogram.jar com.mycompany.mypkg.MainAppClass files to add

或者,可以在清單文件中指定程序的主類,包括以下形式的語(yǔ)句:

Main-Class: com.mycompany.mypkg.MainAppClass

不要為主類名加擴(kuò)展名.class。

【警告:清單文件的最后一行必須以換行符結(jié)束。否則,將無(wú)法正確地讀取清單文件。常見(jiàn)的一個(gè)錯(cuò)誤時(shí)創(chuàng)建了一個(gè)只包含Main-Class行而沒(méi)有行結(jié)束符的文本文件。】

不論使用哪一種方法,用戶都可以簡(jiǎn)單地通過(guò)下面的命令來(lái)啟動(dòng)程序:

jar -jar Myprogram.jar

取決于操作系統(tǒng)的配置,用戶甚至可以通過(guò)雙擊JAR文件圖標(biāo)來(lái)啟動(dòng)應(yīng)用程序。下面是各種操作系統(tǒng)的操作方式:

·在Windows平臺(tái)中,Java運(yùn)行時(shí)安裝程序?qū)椤?jar”擴(kuò)展名創(chuàng)建一個(gè)文件關(guān)聯(lián),會(huì)用javaw -jar命令啟動(dòng)文件(與java命令不同,javaw命令不打開(kāi)shell窗口)。

·在Mac OS X平臺(tái)中,操作系統(tǒng)能夠識(shí)別“.jar”擴(kuò)展名文件。雙擊JAR文件時(shí)就會(huì)執(zhí)行Java程序。

不過(guò),人們對(duì)JAR文件中的Java程序與原生應(yīng)用還是感覺(jué)不同。在Windows平臺(tái)中,可以使用第三方的包裝器工具將JAR文件轉(zhuǎn)換成Windows可執(zhí)行文件。包裝器是一個(gè)Windows程序,有大家熟悉的擴(kuò)展名.exe,它可以查找和加載Java虛擬機(jī)(JVM),或者在沒(méi)有找到JVM時(shí)會(huì)告訴用戶應(yīng)該做些什么。有許多商業(yè)的和開(kāi)源的產(chǎn)品,例如,Launch4J(http://launch4j.sourceforge.net)和IzPack(http://izpack.org)。

?

多版本JAR文件:

隨著模塊和包強(qiáng)封裝的引入,之前可以訪問(wèn)的一些內(nèi)部API不再可用。這可能要求庫(kù)提供商為不同Java版本發(fā)布不同的代碼。為此,java9引入了多版本JAR(multi-release JAR)。

為了保證向后兼容,特定于版本的類文件放在META-INF/versions目錄中:

Application.class

BuildingBlocks.class

Util.class

META-INF

->MANIFEST.MF(with line Multi-Release: true)、

??Versions

->9->Application.class

???->BuildingBlocks.class

->10->BuildingBlocks.class

假設(shè)Application類使用了CssParser類,那么遺留版本的Application.class文件可以使用com.sun.javafx.css.CssParer,而Java9版本可以使用javafx.css.Cssparser。

Java8完全不知道META-INF/versions目錄,它只會(huì)加載遺留的類。Java9讀取這個(gè)JAR文件時(shí),則會(huì)使用新版本。

要增加不同的版本的類文件,可以使用--release標(biāo)志:

Jar uf MyProgram.jar --release 9 Application.class

要從頭構(gòu)建一個(gè)多版本JAR文件,可以使用-C選項(xiàng),對(duì)應(yīng)每個(gè)版本要切換到一個(gè)不同的類文件目錄:

Jar cf Myprogram.jar -C bin/8 . --release 9 -C bin/9 Application.class

面向不同版本編譯時(shí),要使用--release標(biāo)志和-d標(biāo)志來(lái)指定輸出目錄:

Javac -d bin/8 --release 8...

在java9中,-d選項(xiàng)會(huì)創(chuàng)建這個(gè)目錄(如果原先該目錄不存在)。

--release標(biāo)志也是Java9新增的。在較早的版本中,需要使用-source、-target和-bootclasspath標(biāo)志。JDK現(xiàn)在為之前的兩個(gè)API版本提供了符號(hào)文件。在Java9中,編譯時(shí)可以將--release設(shè)置為9、8或7.

多版本JAR并不適用于不同版本的程序或庫(kù)。對(duì)于不同的版本,所有類的公共API都應(yīng)當(dāng)是一樣的。多版本JAR的唯一作用是使你的某個(gè)特定版本的程序或庫(kù)能夠使用多個(gè)不同的JDK版本。如果你新增了功能或者改變了一個(gè)API,就應(yīng)當(dāng)提供一個(gè)新版本的JAR。

【注釋:javap之類的工具并沒(méi)有改造為可以處理多版本JAR文件。如果調(diào)用

javap -classpath Myprogram.jar Application.class

你會(huì)得到類的基本版本(畢竟它與更新的版本應(yīng)該有相同的公共API)。如果必須查看更新的版本,則可以調(diào)用:

javap -classpath Myprogram.jar\!/META-INF/versions/9/Application.class

?

關(guān)于命令行選項(xiàng)的說(shuō)明:

Java開(kāi)發(fā)包(JDK)的命令行選項(xiàng)一直以來(lái)都使用單個(gè)短橫線加多字母選項(xiàng)名的形式,如:

java -jar...
javac -Xlint:unchecked -classpath...

但jar命令是個(gè)例外,這個(gè)命令遵循經(jīng)典的tar命令選項(xiàng)格式,而沒(méi)有短橫線:

jar cvf...

從Java9開(kāi)始,Java工具開(kāi)始轉(zhuǎn)向一種更常用的選項(xiàng)格式,多字母選項(xiàng)名前面加兩個(gè)短橫線,另外對(duì)于常用的選項(xiàng)可以使用單字母快捷方式。例如,調(diào)用Linux ls命令時(shí)可以提供一個(gè)“human-readable”選項(xiàng):

ls --human-readble

或者

ls -h

在Java9中,可以使用--version而不是version,另外可以使用--class-path而不是-classpath。在本書(shū)卷II的第9章中可以看到,--module-path選項(xiàng)有一個(gè)快捷方式-p。

詳細(xì)內(nèi)容可以參見(jiàn)JEP293增強(qiáng)請(qǐng)求(http://openjdk.java.net/jeps/293)。在所有清潔工作中,作者還提出要標(biāo)準(zhǔn)化選項(xiàng)參數(shù)。帶--和多字母選項(xiàng)的參數(shù)用空格或者一個(gè)等號(hào)(=)分隔:

Java --class-path /home/user/classdir...

或者

Javac --class-path=/home/user/classdir...

單字母選項(xiàng)的參數(shù)可以用空格分隔,或者直接跟在選項(xiàng)后面:

Javac -p moduledir...

或者

Javac -pmoduledir...

【警告:后一種方式現(xiàn)在不能使用,而且一般來(lái)講這也不是一個(gè)好主意。如果模塊目錄恰好是arameters或rocessor,這就很容易與遺留的選項(xiàng)(parameters或processor)發(fā)生沖突,這又何必呢?】

無(wú)參數(shù)的單字母選項(xiàng)可以組合在一起:

Jar -cvf Myprogram.jar -e mypackage.MyProgram */*.class

【警告:目前不能使用這種方式,這肯定會(huì)帶來(lái)混淆。假設(shè)javac有一個(gè)-c選項(xiàng),那么javac -cp是指java -c -p還是-cp?】

這就會(huì)帶來(lái)一些混亂,希望過(guò)段時(shí)間能夠解決這個(gè)問(wèn)題,盡管我們想要遠(yuǎn)離這些古老的jar選項(xiàng),但最好還是等到塵埃落定為妙。不過(guò),如果你想做到最現(xiàn)代化,那么可以安全地使用jar命令的長(zhǎng)選項(xiàng):

jar --create --verbose ==file jarFileName file1file2...

對(duì)于單字母選項(xiàng),如果不組合,也是可以使用的:

jar -c -v -f jarFileName file1file2...

?

文檔注釋:

JDK包含一個(gè)很有用的工具,叫做javadoc,它可以由源文件生成一個(gè)HTML文檔。

如果在源代碼中添加以特殊定界符/**開(kāi)始的注釋,那么你也可以很容易生成一個(gè)看上去具有專業(yè)水準(zhǔn)的文檔。這是一種很好的方法,因?yàn)檫@樣可以將代碼與注釋放在一個(gè)地方。應(yīng)該知道,如果將文檔存放在一個(gè)單獨(dú)的文件中,隨著時(shí)間的推移,代碼和注釋很可能出現(xiàn)不一致。不過(guò),如果文檔注釋與源代碼在同一個(gè)文件中,就可以很容易地同時(shí)修改源代碼和注釋,然后重新運(yùn)行javadoc。

?

注釋的插入:

Javadoc實(shí)用工具從下面幾項(xiàng)中抽取信息:

·模塊;

·包;

·公共類與接口;

·公共的和受保護(hù)的字段;

·公共的和受保護(hù)的構(gòu)造器及方法。

第5章中將介紹受保護(hù)特性,第6章中將介紹接口,模塊在卷II的第9章介紹。

可以(而且應(yīng)該)為以上各個(gè)特性編寫(xiě)注釋。各個(gè)注釋放置在所描述特性的前面。注釋以/**開(kāi)始,并以*/結(jié)束。

每個(gè)/**。。。*/文檔注釋包含標(biāo)記以及之后緊跟著的自由格式文本(free-form text)。標(biāo)記以@開(kāi)始,如@since或@param。

自由格式文本的第一個(gè)句子應(yīng)該是一個(gè)概要陳述。Javadoc工具自動(dòng)地將這些句子抽取出來(lái)生成概要頁(yè)。

在自由格式文本中,可以使用HTML修飾符,例如,用于強(qiáng)調(diào)的<em>.....</em>、用于著重強(qiáng)調(diào)的<strong>.....</strong>、用于項(xiàng)目符號(hào)列表的<ul>/<li>以及用于包含圖像的<img..../>等。要鍵入等寬代碼,需要使用{@code.....}而不是<code>......</code>——這樣一來(lái),就不用操心對(duì)代碼的<字符轉(zhuǎn)義了。

【注釋:如果文檔中有到其他文件的鏈接,如圖像文件(例如,圖表或用戶界面組件的圖像),就應(yīng)該將這些文件放到包含源文件的目錄下的一個(gè)子目錄doc-files中國(guó)。Javadoc工具將從源目錄將doc-files目錄及其內(nèi)容復(fù)制到文檔目錄中。在鏈接中需要使用doc-files目錄,例如<imgsrc=”doc-files/uml.png”?alt= “UML dagram”/>

?

類注釋:

類注釋必須放在import語(yǔ)句之后,class定義之前。

下面是一個(gè)類注釋的例子:

/**
?* A{@code Card}object represents a playing card, such
?* as "Queen of Hearts". A card has a suit (Diamond, Heard,
?* Spade or Club) and a value (1 = Ace, 2. . . 10, 11 = Jack,
?* 12 = Queen, 13 = King)
?*/
public class Card {

??????. . .

}

【注釋:沒(méi)有必要在每一行的開(kāi)始都添加*,例如,以下注釋同樣是合法的:

**
??A{@code Card}object represents a playing card, such
??as "Queen of Hearts". A card has a suit (Diamond, Heard,
??Spade or Club) and a value (1 = Ace, 2. . . 10, 11 = Jack,
??12 = Queen, 13 = King)
?*/

不過(guò),大部分IDE會(huì)自動(dòng)提供星號(hào),而且換行改變時(shí),還會(huì)重新放置星號(hào)。】

?

方法注釋:

每個(gè)方法注釋必須放在所描述的方法之前。除了通用標(biāo)記之外,還可以使用下面的標(biāo)記:

·@param variable descripition

這個(gè)標(biāo)記將給當(dāng)前方法的“parameters”(參數(shù))部分添加一個(gè)條目。這個(gè)描述可以占據(jù)多行,并且可以使用HTML標(biāo)記。一個(gè)方法的所有@param標(biāo)記必須放在一起。

·@return description

這個(gè)標(biāo)記將給當(dāng)前方法添加“returns”(返回)部分。這個(gè)描述可以跨多行,并且可以使用HTML標(biāo)記。

·@throws class description

這個(gè)標(biāo)記將添加一個(gè)注釋,表示這個(gè)方法有可能拋出異常。有關(guān)異常的詳細(xì)內(nèi)容將在第7章種討論。

下面是一個(gè)方法注釋的示例:

/**
?* Raises the salary of an employee.
?* @param byPercent the percentage by which to raise the salary (e.g., 10 means 10%)
?* @return the amount of the raise
?*/
public double raiseSalary(double byPercent){
????double raise = this.salary * byPercent / 100;
????this.salary += raise;
????return raise;
}

?

字段注釋:

只需要對(duì)公共字段(通常指的是靜態(tài)常量)增加文檔注釋。例如,

/**
?* The "Hearts" card suit
?*/
public static final int HEARTS = 1;

?

通用注釋:

標(biāo)記@since text會(huì)建立一個(gè)“since”(始于)條目。Text(文本)可以是對(duì)引入這個(gè)特性的版本描述。例如,@since 1.7.1

類文檔注釋中可以使用下面的標(biāo)記:

·@author name

這個(gè)標(biāo)記將建立一個(gè)“author”(作者)條目??梢杂卸鄠€(gè)@author標(biāo)記,每個(gè)@author標(biāo)記對(duì)應(yīng)一個(gè)作者。并不是非得使用這個(gè)標(biāo)記,你的版本控制系統(tǒng)能夠更好地跟蹤作者。

·@version text

這個(gè)標(biāo)記將建立一個(gè)“version”(版本)條目。這里的text可以是對(duì)當(dāng)前版本的任何描述。

通過(guò)@see和@link標(biāo)記,可以使用超鏈接,鏈接到j(luò)avadoc文檔的相關(guān)部分或外部文檔。

標(biāo)記@see reference將在“see also”(參見(jiàn))部分增加一個(gè)超鏈接。它可以用于類中,也可以用于方法中。這里的reference(引用)可以有以下選擇:

1.package.class#feature label
2.<a href=". . .">label</a>
3."test"

第一種情況是最有用的。只要提供類、方法或變量的名字,javadoc就在文檔中插入一個(gè)超鏈接。例如,

@see com.horstmann.corejava.Employee#raiseSalary(double)

會(huì)建立一個(gè)超鏈接,鏈接到com.horstmann.corejava.Employee類的raiseSalary(double)方法??梢允÷园?,甚至把包名和類名都省去,這樣一來(lái),這會(huì)位于當(dāng)前包或當(dāng)前類。

需要注意,一定要使用井號(hào)(#),而不要使用句號(hào)(.)分隔類名與方法名(或類名與變量名)。Java編譯器自身可以熟練地確定句點(diǎn)在分割包、子包、類、內(nèi)部類以及方法和變量時(shí)的不同含義。但是javadoc工具就沒(méi)有這么聰明了,因此必須對(duì)它提供幫助。

如果@see標(biāo)記后面有一個(gè)<字符,就需要指定一個(gè)超鏈接。可以超鏈接到任何URL。例如:

@see <a href="www.horstmann.com/corejava.html">The Core Java home page</a>

在上述各種情況下,都可以指定一個(gè)可選的標(biāo)簽(label),這回顯示為鏈接錨(link anchor)。如果省略了標(biāo)簽,則用戶看到的錨就是目標(biāo)代碼名或URL。

如果@see標(biāo)記后面有一個(gè)雙引號(hào)(“)字符,文本就會(huì)顯示在”see also”部分。例如,

@see "Core Java 2 volume 2"

可以為一個(gè)特性添加多個(gè)@see標(biāo)記,但必須將它們放在一起。

如果愿意,可以在任何文檔注釋中放置指向其他類或方法的超鏈接。可以在注釋中的任何位置插入一個(gè)形式如下的特殊標(biāo)記:

{@link package.class#feature label}

這里的特性描述規(guī)則與@see標(biāo)記的規(guī)則相同。

最后,在Java9中,還可以使用{@index entry}標(biāo)記為搜索框增加一個(gè)條目。

?

包注釋:

可以直接將類、方法和變量的注釋放置在Java源文件中,只要用/**......*/文檔注釋界定就可以了。但是,要想產(chǎn)生包注釋,就需要在每一個(gè)包目錄中添加一個(gè)單獨(dú)的文件??梢杂腥缦聝蓚€(gè)選擇:

1.?提供一個(gè)名為package-info.java的Java文件。這個(gè)文件必須包含一個(gè)初始的Javadoc注釋,以/**和*/界定,后面是一個(gè)package語(yǔ)句。它不能包含更多的代碼或注釋。

2.?提供一個(gè)名為package.html的HTML文件,抽取標(biāo)記<body>. . .</body>之間的所有文本。

?

注釋提取:

在這里,假設(shè)你希望HTML文件將放在名為docDirectory的目錄下。執(zhí)行以下步驟:

1.?切換到源文件目錄,其中包含想要生成文檔的源文件。如果有嵌套的包要生成文檔,例如com.horstmann.corejava,就必須切換到包含子目錄com的目錄(如果提供overview.html文件的話,這就是這個(gè)文件所在的目錄)。

2.?如果是一個(gè)包,應(yīng)該運(yùn)行命令:

javadoc -d docDirectory nameOfPakage

或者,如果要為多個(gè)包生成文檔,運(yùn)行:

javadoc -d docDirectory nameOfPakage1 nameOfpackage2. . .

如果你的文件在無(wú)名包中,則應(yīng)該運(yùn)行:

javadoc -d docDirectory *.java

如果省略了-d docDirectory選項(xiàng),HTML文件就會(huì)提取到到當(dāng)前目錄下。這樣可能很混亂,因此我不提倡這種做法。

可以使用很多命令行選項(xiàng)對(duì)javadoc程序進(jìn)行微調(diào)。例如,可以使用-auther和-version選項(xiàng)在文檔包含@author和@version標(biāo)記(默認(rèn)情況下,這些標(biāo)記會(huì)被省略)。另一個(gè)很有用的選項(xiàng)是-link,用來(lái)為標(biāo)準(zhǔn)類添加超鏈接。例如,如果使用命令:

javadoc -link http://docs.oracle.com/javase/9/docs/api *.java

那么,所有的標(biāo)準(zhǔn)類庫(kù)的類都會(huì)自動(dòng)地鏈接到Oracle網(wǎng)站的文檔。

如果使用-linksource選項(xiàng),那么每個(gè)源文件就會(huì)轉(zhuǎn)換為HTML(不對(duì)代碼著色,但包含行號(hào)),并且每個(gè)類和方法名將變?yōu)橹赶蛟创a的超鏈接。

還可以為所有源文件提供一個(gè)概要注釋。把它放在一個(gè)類似overview.html的文件中,運(yùn)行javadoc工具,并提供命令行選項(xiàng)-overview filename。將抽取標(biāo)價(jià)<body>......</body>之間的所有文本。當(dāng)用戶從導(dǎo)航欄中選擇“Overview”時(shí),就會(huì)顯示這些內(nèi)容。

有關(guān)其他的選項(xiàng),請(qǐng)查閱javadoc工具的聯(lián)機(jī)文檔http://docs.oracle.com/javase/9/javadoc/javadoc.html。

?

類設(shè)計(jì)技巧:

我們不會(huì)面面俱到,也不希望過(guò)于沉悶,所以在這一章結(jié)束之前再簡(jiǎn)單地介紹幾點(diǎn)技巧。應(yīng)用這些技巧可以使你設(shè)計(jì)的類更能得到專業(yè)OOP圈子的認(rèn)可。

1.一定要保證數(shù)據(jù)私有。

這是最重要的;絕對(duì)不要破壞封裝性。有時(shí)候,可能需要編寫(xiě)一個(gè)訪問(wèn)器方法或更改器方法,但最好還是保持實(shí)例字段的私有性。很多慘痛的教訓(xùn)告訴我們,數(shù)據(jù)的表示形式很可能會(huì)改變,但它們的使用方式卻不會(huì)經(jīng)常變化。當(dāng)數(shù)據(jù)保持私有時(shí),表示形式的變化不會(huì)對(duì)類的使用者產(chǎn)生影響,而且也更容易檢測(cè)bug。

2.一定要初始化數(shù)據(jù)。

Java不會(huì)為你初始化局部變量,但是會(huì)對(duì)對(duì)象的實(shí)例字段進(jìn)行初始化。最好不要依賴于系統(tǒng)的默認(rèn)值,而是應(yīng)該顯式地初始化所有變量,可以提供默認(rèn)值,也可以在所有構(gòu)造器中設(shè)置默認(rèn)值。

3.不要在類中使用過(guò)多的基礎(chǔ)類型。

其想法是要用其他類,而不是使用多個(gè)相關(guān)的基本類型。這樣會(huì)使類更易于理解,也更易于修改。例如,可以用一個(gè)名為Address的新類替換一個(gè)Customer類中的以下實(shí)例字段:

private String street;
private String city;
private String state;
private int zip;

這樣一來(lái),可以很容易地處理地址的變化,例如,可能需要處理國(guó)際地址。

4.不是所有的字段都需要單獨(dú)的字段訪問(wèn)器和更改器。

你可能需要獲得或設(shè)置員工的工資。而一旦構(gòu)造了員工對(duì)象,肯定不需要更改雇傭日期。另外,在對(duì)象中,常常包含一些不希望別人獲得或設(shè)置的實(shí)例字段,例如,Address類中的州縮寫(xiě)數(shù)組。

5.分解有過(guò)多職責(zé)的類。

這樣說(shuō)似乎有點(diǎn)含糊,究竟多少算是“過(guò)多”?每個(gè)人的看法都不同。但是,如果明顯地可以將一個(gè)復(fù)雜的類分解成兩個(gè)概念上更為簡(jiǎn)單的類,就應(yīng)該進(jìn)行分解。(但另一方面,也不要走極端。如果設(shè)計(jì)10個(gè)類,每個(gè)類只有一個(gè)方法,顯然就有些矯枉過(guò)正了。)

下面是一個(gè)反面的設(shè)計(jì)示例。

public class CardDeck // bad design
{
????private int[] value;
????private int[] suit;
????
????public CardDeck(){....}
????public void shuffle{.....}
????public int getTopValue(){.....}
????public int getTopSuit(){.....}
????public void draw(){......}
}

實(shí)際上,這個(gè)類實(shí)現(xiàn)了兩個(gè)獨(dú)立的概念:一副牌(包含shuffle方法和draw方法)和一張牌(包含查看面值和花色的方法)。最好引入一個(gè)表示一張牌的Card類?,F(xiàn)在有兩個(gè)類,每個(gè)類分別完成自己的職責(zé):

public class CardDeck // bad design
{
????private Card[] cards;

????public CardDeck(){....}
????public void shuffle{.....}
????public int getTopValue(){.....}
????public int getTopSuit(){.....}
????public void draw(){......}
}

public class Card
{
????private int value;
????private int suit;
????
????public Card(int aValue, int aSuit){.......}
????public int getValue(){.......}
????public int getSuit(){......}
}

6.類名和方法名要能夠體現(xiàn)它們的職責(zé)。

變量應(yīng)該有一個(gè)能夠反映其含義的名字,類似地,類也應(yīng)該如此(在標(biāo)準(zhǔn)類庫(kù)中,確實(shí)存在著一些含義不明確的例子,如Date類實(shí)際上是一個(gè)描述時(shí)間的類)。

對(duì)此有一個(gè)很好的慣例:類名應(yīng)當(dāng)是一個(gè)名詞(Order),或者是前面有形容詞修飾的名詞(RushOrder),或者是有動(dòng)名詞(有“-ing”后綴)修飾的名詞(例如,BillingAddress)。對(duì)于方法來(lái)說(shuō),要遵循標(biāo)準(zhǔn)慣例:訪問(wèn)器方法用小寫(xiě)get開(kāi)頭(getSalary),更改器方法用小寫(xiě)的set開(kāi)頭(setSalary)。

7.?優(yōu)先使用不可變的類。

LocalDate類以及java.time包中的其他類是不可變的——沒(méi)有方法能夠修改對(duì)象的狀態(tài)。類似plusDays的方法并不會(huì)更改對(duì)象,而是會(huì)返回狀態(tài)已修改的新對(duì)象。

更改對(duì)象的問(wèn)題在于,如果多個(gè)線程試圖同時(shí)更新一個(gè)對(duì)象,就會(huì)發(fā)生并發(fā)更改,其結(jié)果是不可預(yù)料的。如果類是不可變的,就可以安全地在多個(gè)線程間共享其對(duì)象。

因此,要盡可能讓類是不可能變的,這是一個(gè)很好的想法。對(duì)于表示值的類,如一個(gè)字符串或一個(gè)時(shí)間點(diǎn),這尤其容易。計(jì)算會(huì)生成新值,而不是更新原來(lái)的值。

當(dāng)然,并不是所有類都應(yīng)當(dāng)是不可變的。如果員工加薪時(shí)讓raiseSalary方法返回一個(gè)新的Employee對(duì)象,這會(huì)很奇怪。

本章介紹了有關(guān)對(duì)象和類的基礎(chǔ)知識(shí),這使得Java可以作為一種“基于對(duì)象”的語(yǔ)言。要真正做到面向?qū)ο?,程序設(shè)計(jì)語(yǔ)言還必須支持繼承和多態(tài)。Java提供了對(duì)這些特性的支持,具體內(nèi)容將在下一章中介紹。

【學(xué)習(xí)參考書(shū)籍:《Java核心技術(shù)卷I》】?

Java學(xué)習(xí)記錄:對(duì)象與類(二)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
兴业县| 商城县| 三河市| 昭觉县| 开远市| 天长市| 岳阳市| 揭东县| 龙陵县| 曲麻莱县| 瓦房店市| 萝北县| 绥中县| 济阳县| 青海省| 沅陵县| 德钦县| 柯坪县| 伊通| 本溪| 余干县| 青海省| 武城县| 和硕县| 梓潼县| 望江县| 理塘县| 平江县| 五指山市| 临湘市| 蛟河市| 洛扎县| 自治县| 德清县| 中卫市| 贵州省| 新建县| 舟曲县| 天津市| 东丽区| 防城港市|