<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Decode360's Blog

    業(yè)精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
      397 隨筆 :: 33 文章 :: 29 評(píng)論 :: 0 Trackbacks
    Java學(xué)習(xí)(二).類和對(duì)象
    ?
    ?
    ??? Java語(yǔ)言是一種面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言,類和對(duì)象是面向?qū)ο蟪绦蛟O(shè)計(jì)的基本概念。類是相似對(duì)象中共同屬性和方法的集合體。對(duì)象是類的實(shí)例。包是Java組織和管理類的一種方法。類的封裝性是面向?qū)ο蟪绦蛟O(shè)計(jì)的一個(gè)重要特點(diǎn)。
    ?
    ?
    1、面向?qū)ο蟪绦蛟O(shè)計(jì)
    ?
    1.面向?qū)ο蟪绦蛟O(shè)計(jì)的基本概念
    ??? Java語(yǔ)言是一種面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言。面向?qū)ο蟪绦蛟O(shè)計(jì)(Object Oriented Programming,簡(jiǎn)稱OOP)是一種集問(wèn)題分析方法、軟件設(shè)計(jì)方法和人類的思維方法于一體的、貫穿軟件系統(tǒng)分析、設(shè)計(jì)和實(shí)現(xiàn)整個(gè)過(guò)程的程序設(shè)計(jì)方法。面向?qū)ο蟪绦蛟O(shè)計(jì)方法的出發(fā)點(diǎn)和追求的基本目標(biāo),是使我們分析、設(shè)計(jì)和實(shí)現(xiàn)一個(gè)軟件系統(tǒng)的方法盡可能接近我們認(rèn)識(shí)一個(gè)事物的方法。面向?qū)ο蟪绦蛟O(shè)計(jì)的基本思想是:對(duì)軟件系統(tǒng)要模擬的客觀實(shí)體以接近人類思維的方式進(jìn)行自然分割,然后對(duì)客觀實(shí)體進(jìn)行結(jié)構(gòu)模擬和功能模擬,從而使設(shè)計(jì)出的軟件盡可能直接地描述客觀實(shí)體,從而構(gòu)造出模塊化的、可重用的、維護(hù)方便的軟件。
    ??? 在現(xiàn)實(shí)世界中,客觀實(shí)體有兩大類:
    ??? (1)我們身邊存在的一切有形事物和抽象概念都是客觀實(shí)體。有形事物的例子如一個(gè)教師、一件衣服、一本書(shū)、一個(gè)飯店、一座樓、一個(gè)學(xué)校等;抽象概念的例子如學(xué)校校規(guī)、企業(yè)規(guī)定等;
    ??? (2)我們身邊發(fā)生的一切事件都是客觀實(shí)體,例如一場(chǎng)足球比賽、一次流感侵襲、一次到醫(yī)院的就診過(guò)程、一次到圖書(shū)館的借書(shū)過(guò)程,等等。
    ??? 不同的客觀實(shí)體具有各自不同的特征和功能。例如,飯店具有飯店的特征和功能,學(xué)校具有學(xué)校的特征和功能;又例如,就診過(guò)程具有就診過(guò)程的特征和功能,借書(shū)過(guò)程具有借書(shū)過(guò)程的特征和功能。
    ??? 現(xiàn)實(shí)世界中的一切客觀實(shí)體都具有如下特征:
    ??? ?有一個(gè)名字用來(lái)惟一地標(biāo)識(shí)該客觀實(shí)體;
    ??? ?有一組屬性用來(lái)描述其特征;
    ??? ?有一組方法用來(lái)實(shí)現(xiàn)其功能。

    ??? 例如,作為書(shū)店客觀實(shí)體,每個(gè)書(shū)店有不同的點(diǎn)名、負(fù)責(zé)人等屬性(特征),書(shū)店的入庫(kù)、出庫(kù)、圖書(shū)上架等是其基本的方法(功能)。
    ??? 面向?qū)ο蟪绦蛟O(shè)計(jì)方法下的軟件系統(tǒng)設(shè)計(jì)方法,首先是把問(wèn)題中涉及的客觀實(shí)體分割出來(lái),并設(shè)計(jì)成稱為類的可重復(fù)使用的模塊,然后定義出一個(gè)個(gè)實(shí)例化的類(稱為對(duì)象),再按照問(wèn)題的要求,設(shè)計(jì)出用各個(gè)對(duì)象的操作完成的軟件系統(tǒng)。
    ?
    2.
    ??? 在現(xiàn)實(shí)世界中,類這個(gè)術(shù)語(yǔ)是對(duì)一組相似客觀實(shí)體的抽象描述。例如,有A書(shū)店、B書(shū)店、C書(shū)店等。而書(shū)店類則是對(duì)書(shū)店這類客觀實(shí)體所應(yīng)具有的共同屬性和方法的抽象描述。即書(shū)店類不是具體的描述,而是抽象的描述。
    ??? 在面向?qū)ο蠓椒ㄖ校唧w的客觀實(shí)體稱為對(duì)象,類是對(duì)具有相同屬性和相同方法的一組相似對(duì)象的抽象,或者說(shuō),類所包含的屬性和方法描述了一組對(duì)象的共同的屬性和方法。
    ??? 面向?qū)ο蠓椒ㄖ熊浖O(shè)計(jì)的主體是類。類是相同屬性和方法的封裝體,因此類具有封裝性;子類可以在繼承父類所有屬性和方法的基礎(chǔ)上,再增加自己特有的屬性和方法,因此類具有繼承性;在一個(gè)類層次中,定義為根類的對(duì)象可被賦值為其任何子類的對(duì)象,并根據(jù)子類對(duì)象的不同而調(diào)用不同的方法,因此類具有多態(tài)性。類的這種封裝性、多態(tài)性和繼承性,是面向?qū)ο蟪绦蛟O(shè)計(jì)的三個(gè)最重要的特點(diǎn)。
    ?
    3.對(duì)象
    ??? 類是具有相同屬性和方法的一組相似對(duì)象的抽象描述,但在現(xiàn)實(shí)世界中,抽象描述的類是并不具體存在的,例如,現(xiàn)實(shí)世界中只存在具體的A書(shū)店、B書(shū)店、C書(shū)店,并不存在抽象的書(shū)店。我們把按照類這個(gè)模板所定義的一個(gè)個(gè)具體的對(duì)象稱作類的實(shí)例,或稱作對(duì)象。
    ??? 首先,一個(gè)具體對(duì)象必須具有具體的屬性值,如A書(shū)店對(duì)象就必須具有如下屬性:書(shū)點(diǎn)名為A書(shū)店,負(fù)責(zé)人為張三等。其次,任何對(duì)象都具有相應(yīng)類所規(guī)定的所有方法。
    ?
    ?
    2、

    ??? 面向?qū)ο蠓椒ㄖ校浖O(shè)計(jì)的最主要部分是設(shè)計(jì)類。類的設(shè)計(jì)可以劃分為類聲明和類主體設(shè)計(jì)兩部分。
    ?
    1、類聲明
    ?
    1.類聲明的格式
    ??? 類聲明的格式如下:
    ??? [<修飾符>] class<類名>[extends<父類名>] [implements<接口名表>]
    ??? {
    ????? 類主體
    ??? }

    ??? 其中,class是定義類的關(guān)鍵字,<類名>是所定義的類的名字,<父類名>是已經(jīng)定義過(guò)的類名,<接口名表>是已經(jīng)定義過(guò)的若干個(gè)接口名,當(dāng)接口名多于一個(gè)時(shí),用逗號(hào)分隔開(kāi)。方括號(hào)表示該項(xiàng)是可選項(xiàng)。本章只討論基本的類設(shè)計(jì)方法,含有父類和接口的類將在下一章討論。
    ?
    2.類的修飾符
    ???
    類聲明的<修飾符>分為訪問(wèn)控制符類型說(shuō)明符兩部分,分別用來(lái)說(shuō)明該類的訪問(wèn)權(quán)限以及該類是否為抽象類或最終類。
    ??? ( 1)訪問(wèn)控制符public和默認(rèn)
    ??? 當(dāng)訪問(wèn)控制符為public時(shí),表示該類被定義為公共類。公共類表示該類能被任何類訪問(wèn)。由于類都放于某個(gè)包中,包中的類互相能訪問(wèn),而不在一個(gè)包中的類互相不能直接訪問(wèn)。如果要在一個(gè)包中訪問(wèn)另一個(gè)包中的類,就必須用import語(yǔ)句導(dǎo)入所需要的類到該包中,但Java語(yǔ)言規(guī)定,被導(dǎo)入的類必須是用public修飾的類。
    ??? 當(dāng)沒(méi)有訪問(wèn)控制符public時(shí),即是默認(rèn)類(或稱缺省類)。默認(rèn)類表示該類只能被同一個(gè)包中的類訪問(wèn),而不能被其他包中的類訪問(wèn)。Java語(yǔ)言規(guī)定,一個(gè)Java文件中可以有很多類,但最多只能有一個(gè)公共類,其他都必須定義為默認(rèn)類。
    ??? 例如: public? class? Teacher就聲明了一個(gè)公共類Teacher,該類可以通過(guò)import語(yǔ)句導(dǎo)入到其他包的類中,并能被其他所有的類訪問(wèn)。又例如,class Student就聲明了一個(gè)默認(rèn)類Student,該類只能被同一個(gè)包中的其他類訪問(wèn)。
    ??? ( 2)類型說(shuō)明符abstract和final
    ??? 當(dāng)類型說(shuō)明符為abstract時(shí),表示該類為抽象類,抽象類不能用來(lái)定義對(duì)象,抽象類通常設(shè)計(jì)成一些具有類似成員變量和方法的子類的父類。
    ??? 當(dāng)類型說(shuō)明符為final時(shí),表示該類為最終類,最終類不能用來(lái)再派生子類。
    ??? 訪問(wèn)控制符和類型說(shuō)明符一起使用時(shí),訪問(wèn)控制符在前,類型說(shuō)明符在后。例如,public abstract class Teacher就聲明了一個(gè)公共抽象類Teacher。
    ?
    ?
    2、類主體設(shè)計(jì)

    ???
    在上節(jié)討論面向?qū)ο蟪绦蛟O(shè)計(jì)時(shí)曾說(shuō)過(guò),類由成員變量和成員方法組成。因此,類主體設(shè)計(jì)包括類的成員變量設(shè)計(jì)和類的成員方法設(shè)計(jì)兩部分。由于Java語(yǔ)言中的所有方法必定屬于某個(gè)類,即方法一定是成員方法,所以成員方法可簡(jiǎn)稱為方法。我們首先給出一個(gè)簡(jiǎn)單的日期類設(shè)計(jì),然后分別討論類成員變量和類方法的設(shè)計(jì)。

    【例3.1】設(shè)計(jì)一個(gè)日期類。要求方法應(yīng)包括設(shè)置日期、顯示日期和判斷是否是閏年。
    類設(shè)計(jì)如下:
    public class Date?????????????????? //類聲明
    {
    ? //以下為類成員變量聲明
    ? private int year;?????????????????? //成員變量,表示年
    ? private int month;????????????????? //成員變量,表示月
    ? private int day;??????????????????? //成員變量,表示日
    ???
    ? //以下為類方法聲明和實(shí)現(xiàn)
    ? public void SetDate(int y,int m,int d)???? //設(shè)置日期值
    ??? {?????????????????????????????????
    ????? year = y;
    ????? month = m;
    ????? day = d;
    ??? }
    ???
    ? public void Print()??????????????????????? //輸出日期值
    ??? {
    ????? System.out.println("date is "+year+'-'+month+'-'+day);
    ??? }
    ???????
    ? public boolean IsLeapYear()??????????????? //判斷是否為閏年
    ??? {?????????????????????????????????
    ????? return (year%400==0) | (year%100!=0) & (year%4==0);
    ??? }
    }

    1.聲明成員變量
    ??? 聲明一個(gè)成員變量就是聲明該成員變量的名字及其所屬的數(shù)據(jù)類型,同時(shí)指定其他一些附加特性。聲明成員變量的格式為:
    ??? [<修飾符>] [static] [final] [transient] <變量類型>? <變量名>;
    ??? 其中,<修飾符>有private、public和protected三種。當(dāng)不加任何修飾符時(shí),定義為默認(rèn)修飾符。
    ??? private修飾符表示該成員變量只能被該類本身訪問(wèn),任何其他類都不能訪問(wèn)該成員變量。
    ??? protected修飾符表示該成員變量除可以被該類本身和同一個(gè)包的類訪問(wèn)外,還可以被它的子類(包括同一個(gè)包中的子類和不同包中的子類)訪問(wèn)。
    ??? public修飾符表示該成員變量可以被所有類訪問(wèn)。
    ??? 不加任何訪問(wèn)權(quán)限限定的成員變量屬于默認(rèn)訪問(wèn)權(quán)限。默認(rèn)訪問(wèn)權(quán)限表示該成員變量只能被該類本身和同一個(gè)包的類訪問(wèn)。
    ??? 上述修飾符實(shí)現(xiàn)了類中成員變量在一定范圍內(nèi)的信息隱藏。這既符合程序設(shè)計(jì)中隱藏內(nèi)部信息處理細(xì)節(jié)的原則,也有利于數(shù)據(jù)的安全性。
    ??? static指明該成員變量是一個(gè)類成員變量
    ??? final指明該成員變量是常量
    ??? transient指明該成員變量是臨時(shí)變量。 transient很少使用。
    ??? 類成員變量是一個(gè)類的所有對(duì)象共同擁有的成員變量。關(guān)于類成員變量的用途和使用方法我們將通過(guò)后面的例子說(shuō)明。
    ??? 因此,例3.1中的成員變量year、month和day都是int類型的private成員變量,即這三個(gè)成員變量只能被該類本身訪問(wèn),任何其他類都不能訪問(wèn)該成員變量。
    ?
    2.聲明方法
    ??? 聲明成員方法的格式為:
    ??? [<修飾符>] [static] <返回值類型>?<方法名>? ([<參數(shù)列表>])
    ??? {
    ? ??? <方法體>
    ??? }

    ??? 其中,<修飾符>和成員變量的修飾符一樣,有private、public和protected三種,另外,還有默認(rèn)。
    ??? 各個(gè)修飾符的含義也和成員變量修飾符的含義相同。static指明該方法是一個(gè)類方法。關(guān)于類方法的用途和使用方法我們將通過(guò)后面的例子說(shuō)明。
    ??? 方法聲明中必須給出方法名和方法的返回值類型,如果沒(méi)有返回值,用關(guān)鍵字void標(biāo)記。方法名后的一對(duì)圓括號(hào)是必須的,即使參數(shù)列表為空,也要加一對(duì)空括號(hào)。
    ??? 例如:
    ??? public void SetDate(int y,int m,int d)
    ??? 上述語(yǔ)句聲明了方法名為SetDate的public方法,其返回值為空,參數(shù)有三個(gè),分別為y、m和d,這三個(gè)參數(shù)的數(shù)據(jù)類型均為int。
    ?
    3.方法體
    ??? 方法體是方法的具體實(shí)現(xiàn)。方法體的設(shè)計(jì)即是第2章討論的變量定義、賦值語(yǔ)句、if語(yǔ)句、for語(yǔ)句等根據(jù)方法體設(shè)計(jì)要求的綜合應(yīng)用。例如,
    ??? public void SetDate(int y,int m,int d)???? //設(shè)置日期值
    ??? {?????????????????????????????????
    ????? year = y;??????? //給成員變量year賦值y
    ???? month = m;?????? //給成員變量month賦值m
    ??? day = d;???????? //給成員變量day賦值d
    ??? }
    ?
    4.成員變量和變量
    ???
    初學(xué)者經(jīng)常會(huì)混淆成員變量和變量,一個(gè)最簡(jiǎn)單的區(qū)別方法是:定義在類中的都是成員變量,定義在方法內(nèi)的都是變量。另外,還有定義在方法參數(shù)中的虛參變量,如例3.1 SetDate()中的y、m和 d。關(guān)于方法中定義的變量的例子見(jiàn)后面的設(shè)計(jì)舉例。
    ??? 成員變量和變量的類型既可以是基本數(shù)據(jù)類型(如int、long等),也可以是已定義的類。
    ?
    3、構(gòu)造方法

    ??? 在類的方法中,有一種特殊的方法專門(mén)用來(lái)進(jìn)行對(duì)象的初始化,這個(gè)專門(mén)用來(lái)進(jìn)行對(duì)象初始化的方法稱為構(gòu)造方法。構(gòu)造方法也稱作構(gòu)造函數(shù)。一般來(lái)說(shuō),一個(gè)類中至少要有一個(gè)構(gòu)造方法。
    ??? 構(gòu)造方法在語(yǔ)法上等同于其他方法。因此構(gòu)造方法的設(shè)計(jì)方法和前面說(shuō)的其他方法的設(shè)計(jì)方法類同。但構(gòu)造方法的名字必須與其類名完全相同,并且沒(méi)有返回值,甚至連表示空類型(void)的返回值都沒(méi)有。構(gòu)造方法一般應(yīng)定義為public。
    ??? 構(gòu)造方法用來(lái)在對(duì)象創(chuàng)建時(shí)為對(duì)象的成員變量進(jìn)行初始化賦值。其實(shí)現(xiàn)過(guò)程是:在創(chuàng)建對(duì)象時(shí),將調(diào)用相應(yīng)類中的構(gòu)造方法為對(duì)象的成員變量進(jìn)行初始化賦值。
    ??? 例如,我們可以為上述日期類設(shè)計(jì)一個(gè)如下的構(gòu)造方法:
    ??? public Date(int y, int m, int d)????????? //構(gòu)造方法
    ??? {
    ? ??? year = y;
    ? ??? month = m;
    ? ??? day = d;
    ??? }

    ?
    ?
    3、對(duì)象
    ??? 類是一類相似對(duì)象的抽象描述,一個(gè)軟件系統(tǒng)是對(duì)具體問(wèn)題的客觀事物進(jìn)行模擬或描述的,因此需要具體的描述。對(duì)象是類的實(shí)例化,對(duì)象就是軟件系統(tǒng)中對(duì)具體問(wèn)題的客觀事物進(jìn)行的具體模擬或具體描述。
    ?
    1、main方法
    ?
    ??? 類是作為許多相似對(duì)象的抽象描述設(shè)計(jì)的,如果要使用這個(gè)類時(shí),就必須創(chuàng)建這個(gè)類的對(duì)象。那么,對(duì)象創(chuàng)建應(yīng)該是在同一個(gè)類中呢?還是應(yīng)該在另一個(gè)類中呢?答案是兩者都可以,但最好是在另一個(gè)類中。這樣沒(méi)有對(duì)象定義的純粹的類設(shè)計(jì)部分就可以單獨(dú)保存在一個(gè)文件中,就不會(huì)影響該類的重復(fù)使用。
    ??? Java語(yǔ)言規(guī)定,一個(gè)類對(duì)應(yīng)一個(gè).class文件,一個(gè)程序文件中可以包含一個(gè)或一個(gè)以上的類,但其中只允許一個(gè)類被定義成public類型。類中可以沒(méi)有main方法。但是要運(yùn)行的類中必須有main方法。程序就是從main方法開(kāi)始執(zhí)行的。
    ??? 下面的例子是把對(duì)象創(chuàng)建在同一個(gè)類中的main方法中。
    【例3.2】打印某個(gè)日期,并判斷該年是否是閏年。
    public class Date???????????????????? //類聲明
    {
    ? private int year;?????????????????? //成員變量,表示年
    ? private int month;????????????????? //成員變量,表示月
    ? private int day;??????????????????? //成員變量,表示日
    ? public Date(int y, int m, int d)????????? //構(gòu)造方法
    ? {
    ??? year = y;
    ??? month = m;
    ??? day = d;
    ?? }
    ???
    ? //以下為其他類方法
    ? public void SetDate(int y, int m, int d)???? //設(shè)置日期值
    ? {
    ??? year = y;
    ??? month = m;
    ??? day = d;
    ? }
    ???
    ? public void Print()????????????????????????? //輸出日期值
    ? {
    ??? System.out.println("date is "+year+'-'+month+'-'+day);
    ? }
    ???????
    ? public boolean IsLeapYear()???????????????? //判斷是否閏年
    ? {?????????????????????????????????
    ??? return (year%400==0) | (year%100!=0) & (year%4==0);
    ? }
    ?
    ? public static void main(String args[])?? //main()方法
    ? {
    ??? Date a = new Date(2004, 8, 5) ;??????? //創(chuàng)建對(duì)象
    ??? a.Print();
    ??? if(a.IsLeapYear())
    ????? System.out.println(a.year + " 是閏年");
    ??? else
    ????? System.out.println(a.year + " 不是閏年");
    ? }
    }

    main方法必須放在類中,且格式必須為:public static void main(String args[])

    2、對(duì)象的創(chuàng)建和初始化
    ?
    ??? 在例3.2中,語(yǔ)句Date a = new Date(2004, 8, 5);
    ??? 實(shí)現(xiàn)了定義對(duì)象a和為對(duì)象分配內(nèi)存空間,并初始化對(duì)象a的成員變量數(shù)值為:
    ??? year = 2004; month = 8; day = 5;
    ??? 上述方法是把定義對(duì)象和創(chuàng)建對(duì)象這兩個(gè)步驟結(jié)合在了一起,并同時(shí)進(jìn)行了對(duì)象的初始化賦值。這是最簡(jiǎn)單、也是最經(jīng)常使用的對(duì)象定義、創(chuàng)建和初始化方法。
    ??? 對(duì)象的定義和創(chuàng)建過(guò)程也可以分開(kāi)進(jìn)行,即首先定義對(duì)象,然后為對(duì)象分配內(nèi)存空間,并可同時(shí)進(jìn)行初始化賦值。
    ?
    1.定義對(duì)象
    ??? 定義對(duì)象的語(yǔ)句格式為:
    ??? <類名>?<對(duì)象名>;
    ??? 例如下面語(yǔ)句就定義了一個(gè)Date類的對(duì)象a:
    ??? Date a;
    ??? 對(duì)象和數(shù)組一樣,也是引用類型。即對(duì)象定義后,系統(tǒng)將給對(duì)象標(biāo)識(shí)符分配一個(gè)內(nèi)存單元,用于存放實(shí)際對(duì)象在內(nèi)存中的存放位置。由于在對(duì)象定義時(shí),對(duì)象在內(nèi)存中的實(shí)際存放位置還沒(méi)有給出,所以,此時(shí)該對(duì)象名的值為空(null)。上述語(yǔ)句后對(duì)象a的當(dāng)前狀態(tài)如下圖的(a)所示:
    ??? java(2).01
    ?
    2.為對(duì)象分配內(nèi)存空間和進(jìn)行初始化賦值
    ??? 和為數(shù)組分配內(nèi)存空間一樣,為對(duì)象分配內(nèi)存空間也使用new運(yùn)算符。為對(duì)象分配內(nèi)存空間的語(yǔ)句格式為:
    ??? <對(duì)象名>=? new <類名> ([<參數(shù)列表>]);
    ??? 其中,new運(yùn)算符申請(qǐng)了對(duì)象所需的內(nèi)存空間,new運(yùn)算符返回所申請(qǐng)的內(nèi)存空間的首地址。系統(tǒng)將根據(jù)<類名><參數(shù)列表>調(diào)用相應(yīng)的構(gòu)造方法為對(duì)象進(jìn)行初始化賦值(即把參數(shù)值存入相應(yīng)的內(nèi)存單元中)。賦值語(yǔ)句把new運(yùn)算符分配的連續(xù)地址的首地址賦給了對(duì)象名。正因?yàn)闃?gòu)造方法名和類名完全相同,所以這里的類名既用來(lái)作為new運(yùn)算符的參數(shù)向系統(tǒng)申請(qǐng)對(duì)象所需的內(nèi)存空間,又作為構(gòu)造方法名為對(duì)象進(jìn)行初始化賦值。例如:
    ??? a = new Date(2004, 8, 5) ;
    ??? 就先向系統(tǒng)申請(qǐng)了Date類對(duì)象所需的內(nèi)存空間(其首地址由對(duì)象名a指示),又用參數(shù)2004、8和5調(diào)用了構(gòu)造方法Date(2004, 8, 5),為對(duì)象a進(jìn)行了初始化賦值。上述語(yǔ)句后對(duì)象a的當(dāng)前狀態(tài)如上圖中的(b)所示。

    ??? 程序設(shè)計(jì)時(shí)最經(jīng)常使用的方法,是在定義對(duì)象的同時(shí)為對(duì)象分配內(nèi)存空間和進(jìn)行初始化賦值。例如,
    ??? Date a = new Date(2004, 8, 5) ;
    ?
    3.對(duì)象的使用
    ??? 一旦定義并創(chuàng)建了對(duì)象(創(chuàng)建對(duì)象是指為對(duì)象分配了內(nèi)存單元),就可以在程序中使用對(duì)象。
    ??? 對(duì)象的使用主要有三種情況,分別是:使用對(duì)象的成員變量或方法,對(duì)象間賦值和把對(duì)象作為方法的參數(shù)
    ??? (1) 使用對(duì)象的成員變量或方法
    ??? 一旦定義并創(chuàng)建了對(duì)象,就可以使用對(duì)象的成員變量或方法。
    ??? 例如,例3.2的main()方法中a.year就使用了對(duì)象a的成員變量year。
    ??? 又例如,例3.2的main()方法中a.Print()就使用了對(duì)象a的成員方法Print()。
    ??? 另外,還可以修改對(duì)象的成員變量的數(shù)值,例如,如果在例3.2的main()方法中增加如下語(yǔ)句,就把對(duì)象a的成員變量year的數(shù)值修改為2005,
    ??? a.year = 2005;
    ??? ( 2)對(duì)象間賦值
    ??? 對(duì)象可以像變量一樣賦值。例如,如果在例3.2的main()方法中增加如下語(yǔ)句,則對(duì)象b的值和對(duì)象a的值相同。
    ??? Date b;
    ??? b = a;
    ??? 但和變量賦值不一樣的是,對(duì)象賦值并沒(méi)有真正把一個(gè)對(duì)象的數(shù)值賦給另一個(gè)對(duì)象,而是讓另一個(gè)對(duì)象名(如對(duì)象名b)存儲(chǔ)的對(duì)象的首地址和這個(gè)對(duì)象名(如對(duì)象名a)存儲(chǔ)的對(duì)象的首地址相同。即對(duì)象的賦值是對(duì)象的首地址的賦值。例如,上述語(yǔ)句就把對(duì)象a的首地址值賦給了對(duì)象b,因此,對(duì)象b和對(duì)象a表示的是同一個(gè)對(duì)象。
    ??? 仔細(xì)分析上圖所示的對(duì)象的存儲(chǔ)結(jié)構(gòu),就可以理解對(duì)象間賦值的實(shí)現(xiàn)方法。
    ??? ( 3)把對(duì)象作為方法的參數(shù)
    ??? 對(duì)象也可以像變量一樣,作為方法的參數(shù)使用。但系統(tǒng)實(shí)現(xiàn)兩者的方法不同,變量作為方法的實(shí)參時(shí),系統(tǒng)把實(shí)參的數(shù)值復(fù)制給虛參;而對(duì)象作為方法的實(shí)參時(shí),系統(tǒng)是把實(shí)參對(duì)象名(該對(duì)象必須已創(chuàng)建)指示的對(duì)象的首地址賦給了虛參對(duì)象名。其實(shí)現(xiàn)方法實(shí)際上和對(duì)象間賦值的實(shí)現(xiàn)方法相同。
    ?
    4.垃圾對(duì)象的回收
    ??? 從上面的討論可知,對(duì)象和變量在很多方面有些類同,例如,對(duì)象和變量都需要分配內(nèi)存空間。但是,變量的內(nèi)存空間是系統(tǒng)在變量定義時(shí)自動(dòng)分配的,當(dāng)變量超出作用范圍時(shí),系統(tǒng)將自動(dòng)回收該變量的內(nèi)存空間。
    ??? 而對(duì)象的內(nèi)存空間是在用戶需要時(shí),用new運(yùn)算符創(chuàng)建的。對(duì)象也有作用范圍,我們把超出作用范圍的對(duì)象(或稱不再被使用的對(duì)象)稱作垃圾對(duì)象。那么,誰(shuí)來(lái)負(fù)責(zé)這些垃圾對(duì)象的回收呢?答案是,在Java中,收集和釋放內(nèi)存是一個(gè)叫做自動(dòng)垃圾回收線程的責(zé)任。線程的概念將在第10章討論,這里可以把自動(dòng)垃圾回收線程理解為一個(gè)系統(tǒng)自己開(kāi)啟、并與用戶程序并行運(yùn)行的一個(gè)服務(wù)程序。自動(dòng)垃圾回收線程在系統(tǒng)空閑時(shí)自動(dòng)運(yùn)行,這個(gè)線程監(jiān)視用戶程序中所有對(duì)象的有效作用范圍,當(dāng)某個(gè)對(duì)象超出其作用范圍時(shí),該線程就對(duì)這樣的對(duì)象做上垃圾對(duì)象標(biāo)識(shí),并在適當(dāng)?shù)臅r(shí)候一次性回收這些垃圾對(duì)象。
    ??? 所以,用戶程序只需考慮為對(duì)象分配內(nèi)存空間,不需考慮垃圾對(duì)象內(nèi)存空間的回收
    ?
    5.實(shí)例成員變量與類成員變量
    ??? 類有兩種不同類型的成員變量:實(shí)例成員變量類成員變量。類成員變量也稱作靜態(tài)成員變量。
    ?
    ??? (1) 實(shí)例成員變量
    ??? 類定義中沒(méi)用關(guān)鍵字static修飾的成員變量就是實(shí)例成員變量,不同對(duì)象的實(shí)例成員變量其值不相同。
    ??? 例3.2中類Date的成員變量定義語(yǔ)句:
    ??? private int year;
    ??? private int month;
    ??? private int day;
    ??? 就定義了三個(gè)private類型的實(shí)例成員變量year、month和day。
    ??? 例如,若有如下對(duì)象定義:
    ??? Date a = new Date(2003, 1, 1) ;
    ??? Date b = new Date(2004, 5, 10) ;
    ??? 則對(duì)象a和對(duì)象b的實(shí)例成員變量數(shù)值就不同。如a.year的數(shù)值為2003,而b.year的數(shù)值為2004。
    ?
    ??? (2) 類成員變量
    ??? 用關(guān)鍵字static修飾的成員變量稱為類成員變量,一個(gè)類的所有對(duì)象共享該類的類成員變量。類成員變量可以用來(lái)保存和類相關(guān)的信息,或用來(lái)在一個(gè)類的對(duì)象間交流信息。
    【例3.3】用類成員變量表示當(dāng)前該類共有多少個(gè)對(duì)象被定義。
    public class ObjectNumber???? //類聲明
    {
    ? private static int number = 0;?? //類成員變量
    ???
    ? public ObjectNumber()???? //構(gòu)造方法
    ? {?????????????????????????????????
    ??? number++;
    ? }
    ???
    ? public void Print()????? //對(duì)象個(gè)數(shù)輸出
    ? {
    ??? System.out.println(number);
    ? }
    ???????
    ? public static void main(String args[])
    ? {
    ??? ObjectNumber a = new ObjectNumber() ;?? //創(chuàng)建對(duì)象
    ??? System.out.print("當(dāng)前對(duì)象個(gè)數(shù)為:");
    ??? a.Print();???????? //對(duì)象個(gè)數(shù)輸出
    ??? ObjectNumber b = new ObjectNumber() ;?? //創(chuàng)建對(duì)象?
    ??? System.out.print("當(dāng)前對(duì)象個(gè)數(shù)為:");
    ??? b.Print();???????? //對(duì)象個(gè)數(shù)輸出
    ? }
    }
    輸出結(jié)果為:
    當(dāng)前對(duì)象個(gè)數(shù)為:1
    當(dāng)前對(duì)象個(gè)數(shù)為:2

    ?
    6.實(shí)例方法與類方法
    ??? 類有兩種不同類型的方法:實(shí)例方法與類方法。類方法也稱作靜態(tài)方法。
    ??? ( 1)實(shí)例方法
    ??? 沒(méi)用關(guān)鍵字static修飾的方法就是實(shí)例方法。實(shí)例方法只能通過(guò)對(duì)象來(lái)調(diào)用。實(shí)例方法既可以訪問(wèn)類成員變量,也可以訪問(wèn)類變量。例3.2中類Date的SetDate()方法、 Print()方法和IsLeapYear()方法都是實(shí)例方法。這些實(shí)例方法體中都訪問(wèn)了實(shí)例成員變量。
    ??? (2) 類方法
    ??? 用關(guān)鍵字static修飾的方法稱為類方法。類方法通過(guò)類名來(lái)調(diào)用(也可以通過(guò)對(duì)象來(lái)調(diào)用)。類方法只能訪問(wèn)類變量,不能訪問(wèn)實(shí)例變量。類方法主要用來(lái)處理和整個(gè)類相關(guān)的數(shù)據(jù)。雖然類方法既可以用類名來(lái)調(diào)用,也可以用對(duì)象來(lái)調(diào)用,但用類名調(diào)用類方法程序的可讀性更好。

    【例3.4】用類方法處理當(dāng)前該類共有多少個(gè)對(duì)象被定義。
    程序設(shè)計(jì)如下:
    public class ObjectNumber2???? ??? //類聲明
    {
    ? private static int number = 0;?? //類成員變量
    ???
    ? public ObjectNumber2()???? ????? //構(gòu)造方法
    ? {
    ??? number++;
    ? }
    ???
    ? public static void Print()??? ?? //類方法
    ? {
    ??? System.out.println("當(dāng)前對(duì)象個(gè)數(shù)為:" + number);
    ? }
    ???????
    ? public static void main(String args[])
    ? {
    ??? ObjectNumber2 a = new ObjectNumber2() ;? //創(chuàng)建對(duì)象
    ??? ObjectNumber2.Print();???? ?? //對(duì)象個(gè)數(shù)輸出
    //? a.Print();//可以,但不提倡
    ??? ObjectNumber2 b = new ObjectNumber2() ;? //創(chuàng)建對(duì)象?
    ??? ObjectNumber2.Print();????? ?? //對(duì)象個(gè)數(shù)輸出
    //? b.Print();//可以,但不提倡
    ??? }
    }
    輸出結(jié)果為:
    當(dāng)前對(duì)象個(gè)數(shù)為:1
    當(dāng)前對(duì)象個(gè)數(shù)為:2

    ?
    7.方法的重寫(xiě)
    ??? 類的各種方法(包括構(gòu)造方法和其他方法)都允許重寫(xiě)(也稱做重載)。所謂方法重寫(xiě)(overloading),是指一個(gè)方法名定義了多個(gè)方法實(shí)現(xiàn)。方法重寫(xiě)時(shí)要求,不同的方法,其參數(shù)類型或參數(shù)個(gè)數(shù)要有所不同。若類的某個(gè)方法被重寫(xiě),該類的對(duì)象在訪問(wèn)該方法時(shí),以對(duì)象調(diào)用該方法的參數(shù)個(gè)數(shù)和參數(shù)類型與類的同名方法進(jìn)行匹配,對(duì)象調(diào)用該方法的參數(shù)個(gè)數(shù)和參數(shù)類型與類定義中哪個(gè)方法的參數(shù)個(gè)數(shù)和參數(shù)類型完全一樣,則調(diào)用類中的哪個(gè)方法。
    【例3.5】方法重寫(xiě)示例。
    public class Date2??????????????????? //類聲明
    {
    ? private int year;?????????????????? //成員變量,表示年
    ? private int month;????????????????? //成員變量,表示月
    ? private int day;??????????????????? //成員變量,表示日
    ????
    ? public Date2(int y, int m, int d)?? //構(gòu)造方法
    ? {
    ??? year = y;
    ??? month = m;
    ??? day ? = d;
    ? }
    ???
    ? public Date2()??????????? ????????? //構(gòu)造方法
    ? {
    ??? year = 2004;
    ??? month = 8;
    ??? day? = 10;
    ? }
    ???
    ? public void Print()???????????????? //輸出日期值
    ? {
    ??? System.out.println("date is "+year+'-'+month+'-'+day);
    ? }
    ???
    ? public void Print(int y)??????????? //輸出日期值
    ? {
    ??? System.out.println("date is "+y+'-'+month+'-'+day);
    ? }
    ???????????
    ? public static void main(String args[])
    ? {
    ??? Date2 a = new Date2(2003,1,1) ;?? //創(chuàng)建對(duì)象
    ??? Date2 b = new Date2() ;?????????? //創(chuàng)建對(duì)象?
    ??? a.Print();
    ??? b.Print(2000);
    ? }
    }
    程序運(yùn)行輸出:
    date is 2003-1-1
    date is 2000-8-10

    ??? 上述例子中,構(gòu)造方法和Print()方法都重寫(xiě)了兩個(gè)。第一個(gè)構(gòu)造方法有三個(gè)參數(shù),第二個(gè)構(gòu)造方法沒(méi)有一個(gè)參數(shù);第一個(gè)Print()方法沒(méi)有參數(shù),第二個(gè)Print()方法有一個(gè)參數(shù)。在main()方法中,定義對(duì)象a時(shí)有三個(gè)參數(shù),所以和第一個(gè)構(gòu)造方法匹配,定義對(duì)象b時(shí)沒(méi)有參數(shù),所以和第二個(gè)構(gòu)造方法匹配;對(duì)象a調(diào)用方法Print()時(shí)沒(méi)有參數(shù),所以和第一個(gè)Print()方法匹配,對(duì)象b調(diào)用方法Print()時(shí)有一個(gè)參數(shù),所以和第二個(gè)Print()方法匹配。
    ??? 必須注意的是,方法重寫(xiě)時(shí)必須做到:要么參數(shù)個(gè)數(shù)不同,要么參數(shù)類型不同。否則,系統(tǒng)無(wú)法識(shí)別與重寫(xiě)的哪個(gè)方法匹配。但是,如果兩個(gè)重寫(xiě)方法僅返回值的類型不同則不允許
    ?
    ?
    4、
    ??? 面向?qū)ο蟪绦蛟O(shè)計(jì)的一個(gè)特點(diǎn)就是公共類資源可以重用。這樣,在設(shè)計(jì)一個(gè)軟件系統(tǒng)過(guò)程中設(shè)計(jì)的許多公共類(除包含有main方法的公共類外),就可以在以后的軟件系統(tǒng)設(shè)計(jì)中重復(fù)使用。但是,當(dāng)應(yīng)用軟件比較大時(shí),就有許多Java文件,這些Java文件統(tǒng)統(tǒng)放在一個(gè)文件夾中,給以后的軟件資源重用帶來(lái)了許多不便。Java解決此問(wèn)題的方法是包。
    ??? 包(package)是Java提供的文件(即公共類)的組織方式。一個(gè)包對(duì)應(yīng)一個(gè)文件夾,一個(gè)包中可以包括許多類文件。包中還可以再有子包,稱為包等級(jí)。
    ??? Java語(yǔ)言可以把類文件存放在可以有包等級(jí)的不同的包中。這樣,在軟件系統(tǒng)設(shè)計(jì)時(shí),就可以把相關(guān)的一組文件(即相關(guān)的一組公共類)存放在一個(gè)文件夾中,當(dāng)文件夾太大時(shí),還可以設(shè)計(jì)子文件夾按更細(xì)的分類方法存放相關(guān)文件,從而可以大大方便日后的軟件資源重用。Java語(yǔ)言規(guī)定,同一個(gè)包中的文件名必須惟一,不同包中的文件名可以相同。Java語(yǔ)言的包等級(jí)和Windows的文件組織方式完全相同,只是表示方法不同。
    ?
    1、包的建立方法
    ?
    1.定義文件所屬的包
    ??? 簡(jiǎn)單的包的定義語(yǔ)句格式為:
    ??? package <包名>;
    ??? 其中,package是關(guān)鍵字,<包名>是包的標(biāo)識(shí)符。package語(yǔ)句指出了該語(yǔ)句所在文件所有的類屬于哪個(gè)包。
    ??? Java語(yǔ)言規(guī)定,如果一個(gè) Java文件中有package語(yǔ)句,那么package語(yǔ)句必須寫(xiě)在Java源程序的第一行。例如,下面的Java源程序MyClass.java中的類MyClass將屬于包MyPackage。
    ??? package MyPackage;
    ??? public class MyClass;
    ??? {
    ??? ……
    ??? }

    ?
    2.創(chuàng)建包文件夾
    ??? 程序員自定義的包(如前面例子的MyPackage包)必須通知系統(tǒng)其文件夾所在的路徑,這就需要用戶首先創(chuàng)建包的文件夾并設(shè)置包的路徑。創(chuàng)建包文件夾的方法是:
    ??? ( 1)創(chuàng)建與包同名的文件夾
    ??? 例如,我們可以在D盤(pán)根目錄下創(chuàng)建一個(gè)與包同名的文件夾d:\MyPackage。注意,這里的包名MyPackage必須與package語(yǔ)句后的包名大小寫(xiě)完全一致
    ??? ( 2)設(shè)置包的路徑
    ??? 用戶必須通過(guò)設(shè)置環(huán)境變量classpath,把用戶自定義包所在的路徑添加到環(huán)境變量classpath中。例如,作者設(shè)置的包MyPackage其路徑為d:\ ,所以要把d:\添加到環(huán)境變量classpath中。
    ??? 環(huán)境參數(shù)設(shè)置語(yǔ)句應(yīng)改寫(xiě)為:
    ??? set classpath=.;c:\jdk1.3.1\lib;d:\;
    ??? 環(huán)境參數(shù)設(shè)置說(shuō)明:
    ??? ①分號(hào)(;)用來(lái)分隔開(kāi)各項(xiàng)。因此,上述的設(shè)置共有三項(xiàng)。
    ??? ②c:\jdk1.3.1\lib是作者計(jì)算機(jī)上安裝的JDK1.3.1版本的系統(tǒng)包的路徑。
    ??? ③新添加的d:\是用戶自定義包文件夾的上一級(jí)路徑。
    ??? ④新添加的路徑d:\也可放在圓點(diǎn)(.)(表示當(dāng)前工作路徑)前,則操作時(shí)只需把當(dāng)前路徑下編譯成功的.class文件復(fù)制到自定義包文件夾中;如果路徑d:\放在圓點(diǎn)(.)后,則操作時(shí)需把當(dāng)前路徑下編譯成功的.class文件移動(dòng)到自定義包文件夾。

    ??? 當(dāng)多個(gè)Java源程序文件中都有package語(yǔ)句,且package語(yǔ)句后的包名相同時(shí),則說(shuō)明這些類同屬于一個(gè)包。
    ??? 一個(gè)包還可以有子包,子包下還可以有子子包。在這種情況下,可以具體指明一個(gè)類所屬包的完整路徑。所以,完整的package語(yǔ)句格式為:
    ??? package? <包名>[.<子包名>[.<子子包名>…]];
    ??? 其中,在package語(yǔ)句中,圓點(diǎn)(.)起分隔作用;而在Windows的目錄中,圓點(diǎn)(.)和反斜杠(\)等義,即加一個(gè)圓點(diǎn)(.)就表示下一級(jí)目錄。
    ??? 當(dāng)然,要把一個(gè)類放在某個(gè)子包或子子包中,前提條件是已經(jīng)創(chuàng)建了與子包或子子包同名的目錄結(jié)構(gòu)也相同的文件夾。
    ??? ( 3)把編譯生成的.class文件移入包中
    ??? 用戶的源程序文件(即.java文件)通常存放在另外的文件夾中,.java文件編譯后產(chǎn)生的.class文件也存放在和.java文件相同的文件夾中。用戶在編譯.java文件成功后,需要把編譯成功的.class文件移入用戶自定義的包中。要保證包中有相應(yīng)的.class文件,而當(dāng)前工作目錄下沒(méi)有。
    ??? 例如,當(dāng)上述的 MyClass.java文件編譯成功后,需要設(shè)計(jì)人員自己把MyClass.class文件移入到d:\ MyPackage文件夾中,否則系統(tǒng)會(huì)因找不到類而給出出錯(cuò)信息。
    ?
    2、包的使用方法
    ?
    ??? 包中存放的是編譯后的類文件(.class文件)。用戶可以在以后的程序中,通過(guò)import語(yǔ)句導(dǎo)入這些類,從而使用包中的這些類。
    ??? import語(yǔ)句的使用分兩種情況:
    ??? (1)導(dǎo)入某個(gè)包中的某個(gè)類;
    ??? (2)導(dǎo)入某個(gè)包中的全部類。
    ??? 這兩種情況分別用如下兩種形式的import語(yǔ)句:
    ??? import? MyPackage.MyClass; //導(dǎo)入包MyPackage中的MyClass類
    ??? import? MyPackage.*;? ???? //導(dǎo)入包MyPackage中的全部類,但不包含其子包

    ??? 要說(shuō)明的是,Java中的包是按類似Windows文件的形式組織的,Windows文件用反斜杠(\)表示一條路徑下的子路徑,而Java用圓點(diǎn)(.)表示一個(gè)包的子包。
    【例3.6】設(shè)計(jì)一個(gè)日期類及其測(cè)試程序。
    要求:把日期類放在包MyPackage中,以便于以后重復(fù)使用。
    程序設(shè)計(jì)如下:

    //Date1.java文件
    package MyPackage;?????? ????????????? //定義類所屬的包
    public class Date1???????????????????? //類聲明
    {
    ? public int year,month,day;?????????? //成員變量,表示年、月、日
    ? public Date1(int y, int m, int d)??? //構(gòu)造方法
    ? {
    ??? year = y;
    ??? month = m;
    ??? day = d;
    ? }
    ? public void print()????????????????? //輸出日期值
    ? {
    ??? System.out.println("日期是:" + year + '-' + month +? '-'+day);
    ? }
    }
    ?
    // UseDate1.java文件
    import MyPackage.Date1;???? ?????????? //導(dǎo)入MyPackage中的Date1類
    public class UseDate1
    {
    ? public static void main(String args[])
    ? {
    ??? Date1 a = new Date1(2004,5,10) ;?? //創(chuàng)建對(duì)象
    ??? a.print();
    ? }
    }
    程序運(yùn)行結(jié)果:
    日期是:2004-5-10

    程序設(shè)計(jì)說(shuō)明:因UseDate1.java文件和Date1.java文件不在一個(gè)包中,所以,UseDate1.java文件要用import語(yǔ)句導(dǎo)入文件中使用的類。
    總結(jié)編寫(xiě)、運(yùn)行上述帶有自定義包Java程序的操作步驟如下:
    (1)創(chuàng)建文件夾。如在本地計(jì)算機(jī)的d盤(pán)創(chuàng)建文件夾MyPackage(d:\MyPackage)
    (2)在環(huán)境變量中添加自定義包的路徑。如在autoexec.bat文件的classpath參數(shù)中添加d:\(注意:若在Windows98下,則設(shè)置完成后要運(yùn)行一下該批處理文件)
    (3)編譯包中類的.java文件。如在DOS下執(zhí)行命令:javac Date1.java
    (4)把編譯成功的.class文件移入包中。如把當(dāng)前工作路徑下的Date1.class文件移動(dòng)到文件夾d:\MyPackage中
    (5)編譯導(dǎo)入包的.java文件。如在DOS下執(zhí)行命令:javac UseDate.java
    (6)運(yùn)行導(dǎo)入包的.class文件。如在DOS下執(zhí)行命令:java UseDate

    ?
    ?
    3、包的訪問(wèn)權(quán)限
    ?
    ??? 關(guān)于包中類的訪問(wèn)權(quán)限已在3.2.1節(jié)討論,關(guān)于包中類的成員變量和方法的訪問(wèn)權(quán)限已在3.2.2節(jié)討論。本節(jié)分相同包中的類和不同包中的類兩種情況舉例說(shuō)明。
    ?
    1.相同包中的類和類的成員的訪問(wèn)權(quán)限
    【例3.7】相同包中的訪問(wèn)權(quán)限舉例。
    程序設(shè)計(jì)如下:
    //文件B1.java
    package MyPackage;???? ??? //文件中定義的兩個(gè)類都在同一個(gè)包
    class C1?????????????????? //C1聲明為缺省類
    {
    ? int number;??????? ????? //默認(rèn)成員變量number
    ? protected int age;?????? //protected成員變量age
    ???
    ? C1(int n, int a)????? ?? //構(gòu)造方法
    ? {
    ??? number = n;
    ??? age = a;
    ? }
    ? public void output()???? // C1類的public方法
    ? {
    ??? System.out.println("number = " + number + "\n" + "age = " + age);
    ? }
    }
    ?
    public class B1??????????? //B1聲明為public類??????????
    {
    ? public void output()???? //B1類的方法output()
    ? {
    ??? C1 s1 = new C1(0,0);? //B1類可以訪問(wèn)同一個(gè)包中的默認(rèn)類C1
    ??? s1.number = 1;?? ????? //同一包的對(duì)象可以訪問(wèn)默認(rèn)類的默認(rèn)成員變量
    ??? s1.age = 25;???? ???? //同一包的對(duì)象可以訪問(wèn)默認(rèn)類的protected成員變量
    ??? s1.output();?????? ? ? //同一包的對(duì)象可以訪問(wèn)默認(rèn)類的public方法
    ? }
    }
    ?
    //文件D1.java
    //類D1在當(dāng)前工作路徑下
    import MyPackage.B1;???? ? //導(dǎo)入MyPackage包中的B1類
    public class D1
    {
    ?public static void main(String args[])
    ?{
    ??? B1 t1 = new B1();
    ??? t1.output();
    ? }
    }
    程序的運(yùn)行結(jié)果為:
    number = 1
    age = 25

    程序說(shuō)明:D1類中只能定義B1類的對(duì)象,不能定義C1類的對(duì)象(因C1類定義為默認(rèn)類);但B1類中可以定義C1類的對(duì)象(因兩個(gè)類在同一個(gè)包中)。

    ?
    2.不同包中的類和類的成員的訪問(wèn)權(quán)限
    ?
    【例3.8】不同包中的訪問(wèn)權(quán)限舉例。
    要求:把例3.7中的C1類和B1類分別放在兩個(gè)不同的包中。
    程序設(shè)計(jì)如下:
    //文件C2.java
    package MyPackage.MyPackage1;
    public class C2
    {
    ? public int number;
    ? public int age;??
    ??
    ? public C2(int n, int a)
    ? {
    ??? number = n;
    ??? age = a;
    ? }
    ? public void output()
    ? {
    ??? System.out.println("number = " + number + "\n" + "age = " + age);
    ? }
    }
    ?
    //文件B2.java
    package MyPackage;
    import MyPackage.MyPackage1.C2;
    public class B2?????????????
    {
    ?public void output()
    ? {
    ??? C2 s1 = new C2(0,0);
    ??? s1.number = 1;?
    ??? s1.age = 25;???
    ??? s1.output();????
    ? }
    }
    ?
    //文件D2.java
    import MyPackage.B2;
    public class D2???????????
    {
    ?public static void main(String args[])
    ?{
    ??? B2 t1 = new B2();
    ??? t1.output();
    ? }
    }
    程序的運(yùn)行結(jié)果和例3.7的相同。

    程序設(shè)計(jì)說(shuō)明:
    ??? (1)把例3.7程序稍做改變,把C2類放在MyPackage.MyPackage1包中(當(dāng)然,要建立相應(yīng)的文件夾),把B2類放在MyPackage包中。當(dāng)然,B2.java文件中要用import語(yǔ)句導(dǎo)入C2類。此時(shí),由于B2類和C2類不在同一個(gè)包中,而C2類定義為默認(rèn)類,所以編譯時(shí)語(yǔ)句:
    ??? C2 s1 = new C2(0,0);將出錯(cuò)
    ??? 把C2類定義為public類后,則不會(huì)出現(xiàn)上述錯(cuò)誤。但是,由于B2類和C2類不在同一個(gè)包中,所以編譯時(shí)語(yǔ)句:
    ??? s1.number = 1;
    ??? s1.age = 25;將出錯(cuò)
    ??? 這是由于C2類的age成員變量定義為protected,number定義為默認(rèn),而修飾為protected和默認(rèn)的成員變量不允許其他包中的C2類的對(duì)象調(diào)用;當(dāng)把C2類的age和numbe成員變量的修飾符改為public,編譯成功。
    ??? (2)如果把C2類放在MyPackage包中,把B2類放在MyPackage.MyPackage1包中,則編譯時(shí)會(huì)出錯(cuò)。這是由于JDK規(guī)定:在一個(gè)樹(shù)型結(jié)構(gòu)的包中,上層包可以導(dǎo)入下層包,而下層包不可以導(dǎo)入上層包。在下層包的類中要使用上層包的類時(shí),要在類前面加上包名。
    ?
    4、系統(tǒng)定義的包
    ?
    ??? Java語(yǔ)言提供了許多方便用戶程序設(shè)計(jì)的基礎(chǔ)類,這些系統(tǒng)定義的類以包的形式保存在系統(tǒng)包文件夾中。如果要使用這些包中的類,必須在源程序中用import語(yǔ)句導(dǎo)入。其導(dǎo)入方法和前面介紹的導(dǎo)入自定義包方法類同。例如,要進(jìn)行圖形用戶界面設(shè)計(jì),需要導(dǎo)入系統(tǒng)包java.awt中的所有類,所以要在源程序中使用如下導(dǎo)入語(yǔ)句:
    ??? import? java.awt.*;???? //導(dǎo)入java.awt包中的所有類
    ??? 又例如,在進(jìn)行圖形用戶界面設(shè)計(jì)時(shí),還需要進(jìn)行事件處理,因此需要導(dǎo)入圖形用戶界面包java.awt中的所有類和事件處理包java.awt.event中的所有類,所以要在源程序中使用如下導(dǎo)入語(yǔ)句:
    ??? import java.awt.*;???? //導(dǎo)入java.awt包中的所有類
    ??? import java.awt.event.*;?? //導(dǎo)入java.awt.event包中的所有類
    ??? 讀者也許會(huì)想,從Java語(yǔ)言包的組織形式看,顯然,java.awt.event包是java.awt包的子包,那么,僅有第一條導(dǎo)入語(yǔ)句似乎就可以了,第二條導(dǎo)入語(yǔ)句似乎沒(méi)有必要。
    ??? 讀者需要注意:第一條導(dǎo)入語(yǔ)句只導(dǎo)入了java.awt包中的所有類,并沒(méi)有導(dǎo)入java.awt包的子包,因此,也就沒(méi)有導(dǎo)入子包中的類。
    ?
    ?
    5、內(nèi)部類
    ?
    ??? 一個(gè)類被嵌套定義于另一個(gè)類中,稱為內(nèi)部類(Inner Classes)或內(nèi)隱類。包含內(nèi)部類的類稱為外部類。
    ??? 內(nèi)部類中還有一種更特殊的形式——匿名類,匿名類和內(nèi)部類的功能類似。這里我們只討論內(nèi)部類,不討論匿名類。
    ??? 內(nèi)部類與前面討論的非內(nèi)部類的設(shè)計(jì)方法基本相同,但除外部類外的其他類無(wú)法訪問(wèn)內(nèi)部類。當(dāng)一個(gè)類只在某個(gè)類中使用,并且不允許除外部類外的其他類訪問(wèn)時(shí),可考慮把該類設(shè)計(jì)成內(nèi)部類。
    ?
    【例3.9】設(shè)計(jì)一個(gè)人員類,要求自動(dòng)生成人員的編號(hào)。
    設(shè)計(jì)思想:由于要自動(dòng)生成人員的編號(hào),因此可設(shè)計(jì)一個(gè)static成員變量,當(dāng)每生成一個(gè)對(duì)象時(shí),該成員變量自動(dòng)加1;由于這樣的處理只是作用于外部類,所以把該處理過(guò)程用內(nèi)部類的方法來(lái)實(shí)現(xiàn)。
    程序設(shè)計(jì)如下:
    public class PeopleCount??? ??? //外部類PeopleCount
    {
    ? private String Name;
    ? private int ID;?????????????? //外部類的私有成員變量
    ? private static int count = 0; //外部類的static私有成員變量???
    ? public class People?????????? //內(nèi)部類People
    ? {
    ??? public People()???? ??????? //內(nèi)部類的構(gòu)造方法
    ??? {
    ????? count++;????? ??????????? //訪問(wèn)外部類的成員變量
    ????? ID = count;???? ????????? //訪問(wèn)外部類的成員變量
    ???? }
    ???? public void output()?? ??? //內(nèi)部類的方法
    ???? {
    ?????? System.out.println(Name + "的ID為:" + ID);
    ???? }
    ?? }
    ?? public PeopleCount(String sn) //外部類的構(gòu)造方法
    ?? {
    ???? Name = sn;
    ?? }
    ?
    ?? public void output()????????? //外部類的方法
    ?? {
    ???? People p = new People();??? //建立內(nèi)部類對(duì)象p
    ???? p.output();???????????????? //通過(guò)p調(diào)用內(nèi)部類的方法
    ?? }
    ?? public static void main (String args[])
    ?? {
    ???? PeopleCount p1 = new PeopleCount("張三");
    ???? p1.output();
    ???? PeopleCount p2 = new PeopleCount("李四");
    ???? p2.output();???????
    ?? }
    }
    程序的運(yùn)行結(jié)果為:
    張三的ID為:1
    李四的ID為:2

    ??? 程序設(shè)計(jì)說(shuō)明:
    ??? 在外部類PeopleCount內(nèi)嵌套定義了一個(gè)內(nèi)部類People,當(dāng)定義了外部類對(duì)象p1和p2后,調(diào)用p1或p2的方法output時(shí),該方法將首先定義一個(gè)內(nèi)部類對(duì)象,內(nèi)部類對(duì)象的構(gòu)造方法將先把外部類的static成員變量count加1,然后把count的值賦給人員編號(hào)成員變量PeopleID,然后輸出PeopleID的值。
    ??? 外部類與內(nèi)部類的訪問(wèn)原則是:在外部類中,一般通過(guò)一個(gè)內(nèi)部類的對(duì)象來(lái)訪問(wèn)內(nèi)部類的成員變量或方法;在內(nèi)部類中,可以直接訪問(wèn)外部類的所有成員變量和方法(包括靜態(tài)成員變量和方法、實(shí)例成員變量和方法及私有成員變量和方法)。
    ??? 內(nèi)部類具有以下特性:
    ? 內(nèi)部類作為外部類的成員。Java將內(nèi)部類作為外部類的一個(gè)成員,因此內(nèi)部類可以訪問(wèn)外部類的私有成員變量或方法。
    ? 內(nèi)部類的類名只能用在外部類和內(nèi)部類自身中。當(dāng)外部類引用內(nèi)部類時(shí),必須給出完整的名稱,且內(nèi)部類的類名不能與外部類的類名相同。
    ??? 在實(shí)際的Java程序設(shè)計(jì)中,內(nèi)部類主要用來(lái)實(shí)現(xiàn)接口。

    ?
    ?
    6、類的封裝性
    ?
    ??? 面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言的一個(gè)重要特性是其封裝性,Java語(yǔ)言是按類劃分程序模塊的,Java語(yǔ)言很好地實(shí)現(xiàn)了類的封裝性。
    ??? 保證大型軟件設(shè)計(jì)正確性和高效性的一個(gè)重要原則是模塊化軟件設(shè)計(jì)。這需要設(shè)計(jì)許多可重復(fù)使用的模塊,然后在需要使用這些模塊的地方調(diào)用這些模塊。但是,如何劃分好模塊的界限,以保證模塊的正確性是非常重要的問(wèn)題。因?yàn)槿绻橙穗S意修改了已經(jīng)被其他人使用的模塊,必將使程序出錯(cuò),并且這樣的錯(cuò)誤很難發(fā)現(xiàn)和修改。
    ??? 在面向?qū)ο蟪绦蛟O(shè)計(jì)中,保證模塊正確性的基本方法是類的封裝性類的封裝性是指類把成員變量和方法封裝為一個(gè)整體,這就劃分了模塊的界限。
    ??? 保證模塊正確性的措施則是由信息的隱藏性來(lái)實(shí)現(xiàn)的。類包括成員變量和方法兩部分。那些允許其他包程序訪問(wèn)和修改的成員變量可以定義為public類型。那些只允許同在一個(gè)包中的其他類以及該類的子類訪問(wèn)和修改的成員變量可以定義為protected類型。那些不允許其他類(內(nèi)部類除外)訪問(wèn)和修改的成員變量可以定義為private類型。我們說(shuō),private類型和protected類型的成員變量有效地隱藏了類的不能被隨意修改的成員變量信息,從而保證了共享的類模塊的正確性。類的封裝性和信息的隱藏性是雙胞胎,兩者是結(jié)合在一起的。
    ??? 同樣,那些允許其他包程序訪問(wèn)的方法可以定義為public類型。那些只允許同在一個(gè)包中的其他類以及該類的子類訪問(wèn)的方法可以定義為protected類型。那些不允許其他類(內(nèi)部類除外)訪問(wèn)的方法可以定義為private類型。類方法的不同類型定義,給調(diào)用者提供了權(quán)限明了的調(diào)用接口。
    ??? 和別的面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言(如C++語(yǔ)言)相比,Java語(yǔ)言增加了包的概念。這樣,同一個(gè)包中類之間的信息傳遞就比較方便。
    ?
    7、設(shè)計(jì)舉例
    ?
    ??? 本節(jié)給出一個(gè)較為復(fù)雜的程序設(shè)計(jì)舉例。
    【例3.10】設(shè)計(jì)一個(gè)包括矩陣加和矩陣減運(yùn)算的矩陣類,并設(shè)計(jì)一個(gè)測(cè)試程序完成簡(jiǎn)單的測(cè)試。為簡(jiǎn)化設(shè)計(jì)代碼,矩陣的元素值在構(gòu)造方法中用隨機(jī)函數(shù)隨機(jī)給出。
    程序設(shè)計(jì)如下:
    //MyMatrix.java文件
    public class MyMatrix????? //矩陣類MyMatrix
    {
    private int[][] table;??? //矩陣元素表
    ?? private int height;???? //矩陣的行
    ?? private int width;????? //矩陣的列
    ?
    ?? private void init(int m,int n)? //元素隨機(jī)賦值方法
    ?? {
    ????? table=new int[m][n];?? //分配矩陣元素?cái)?shù)組內(nèi)存空間
    ????? for(int i=0; i<m; i++)
    ??????? for(int j=0; j<n; j++)
    ??????? {
    ?????????? table[i][j]=(int)(Math.random() * 100); //元素隨機(jī)賦值
    ??????? }
    ? }
    ?
    ?? public MyMatrix(int n)??? //構(gòu)造方法,構(gòu)造方陣
    ?? {
    ?????? height = n;?????
    ?????? width = n;
    ?????? this.init(height,width);? //調(diào)用元素隨機(jī)賦值方法
    ?? }
    ?
    ?? public MyMatrix(int m,int n)?? //構(gòu)造方法,構(gòu)造m行n列矩陣
    ?? {
    ????? height=m;
    ????? width=n;
    ????? this.init(height,width);?? //調(diào)用元素隨機(jī)賦值方法
    ?? }
    ?
    ?? public int getHeight()??? //返回矩陣的行數(shù)方法
    ?? {
    ????? return height;
    ?? }
    ?
    ?? public int getWidth()??? //返回矩陣的列數(shù)方法
    ?? {
    ????? return width;
    ?? }
    ?
    ?? public int[][] getTable()?? //返回矩陣方法
    ?? {
    ????? return table;
    ?? }
    ?
    ?? public MyMatrix add(MyMatrix b)? //矩陣加方法
    ??? {?????
    if(this.getHeight()!=b.getHeight()&&
    this.getWidth()!=b.getWidth())
    ????? {
    ??????? System.out.println("the two matrix don't macth");
    ??????? return null;
    ????? }
    ????? MyMatrix result=new MyMatrix(b.getHeight(),b.getWidth());
    ????? for(int i=0;i<b.getHeight();i++)
    ??????? for(int j=0;j<b.getWidth();j++)
    ??????? {
    ?????????? result.table[i][j]=this.table[i][j]+b.table[i][j];
    ??????? }
    ????? return result;
    ?? }
    ?
    ?? public MyMatrix subtract(MyMatrix b)??? //矩陣減方法
    ?? {
    ????? if(this.getHeight()!=b.getHeight()&&
    this.getWidth()!=b.getWidth())
    ????? {
    ??????? System.out.println("the two matrix don't macth");
    ??????? return null;
    ????? }
    ?
    ????? MyMatrix result=new MyMatrix(b.getHeight(),b.getWidth());
    ????? for(int i=0;i<b.getHeight();i++)
    ??????? for(int j=0;j<b.getWidth();j++)
    ??????? {
    ?????????? result.table[i][j]=this.table[i][j]-b.table[i][j];
    ??????? }
    ????? return result;
    ?? }
    }
    ?
    // TestMyMatrix.java文件
    public class TestMyMatrix??????? //測(cè)試類
    {
    ?? public static void main(String[] args)
    ?? {
    ???? MyMatrix mm1=new MyMatrix(4,4);
    ???? MyMatrix mm2=new MyMatrix(4,4);
    ???? MyMatrix mm3=new MyMatrix(4,5);
    ???? MyMatrix mm4=new MyMatrix(4,5);
    ?
    ???? MyMatrix add_result=mm1.add(mm2);
    ???? int[][] add_table=add_result.getTable();
    ???? MyMatrix subtract_result=mm3.subtract(mm4);
    ???? int[][] subtract_table=subtract_result.getTable();
    ?
    ???? System.out.println("two matrix add result:");
    ???? for(int i=0;i<add_result.getHeight();i++)
    ???? {
    ?????? for(int j=0;j<add_result.getWidth();j++)
    ?????? {
    ????????? System.out.print(add_table[i][j]+"? ");
    ?????? }
    ?????? System.out.println();
    ???? }
    ?
    ???? System.out.println("two matrix subtract result:");
    ??? for(int i=0;i<subtract_result.getHeight();i++)
    ??? {
    ?????? for(int j=0;j<subtract_result.getWidth();j++)
    ?????? {
    ???????? System.out.print(subtract_table[i][j]+"? ");
    ?????? }
    ?????? System.out.println();
    ??? }
    ?? }
    }
    程序運(yùn)行結(jié)果如下:
    two matrix add result:
    67? 94? 130? 78
    21? 171? 78? 104
    47? 100? 84? 111
    125? 152? 98? 61
    two matrix subtract result:
    -15? 88? 37? -25? -21
    56? -5? 32? 40? 41
    -56? 31? -75? -21? -4
    -17? -46? -18? 2? -28
    posted on 2008-09-21 22:51 decode360 閱讀(285) 評(píng)論(0)  編輯  收藏 所屬分類: 04.Java

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产日韩久久免费影院| 91制片厂制作传媒免费版樱花| 一个人免费日韩不卡视频| 日韩av无码成人无码免费| 免费少妇a级毛片| 亚洲宅男永久在线| 狠狠入ady亚洲精品| 91人人区免费区人人| 四虎AV永久在线精品免费观看| 久久久久亚洲av无码尤物| 亚洲AV综合色区无码一二三区| 男人进去女人爽免费视频国产| 午夜成年女人毛片免费观看| 久久亚洲国产中v天仙www| 亚洲精品国产摄像头| 午夜精品免费在线观看| 免费一看一级毛片| 91亚洲国产成人久久精品| 成人妇女免费播放久久久| 成人免费无码大片A毛片抽搐 | 91免费福利视频| 女人被弄到高潮的免费视频 | 亚洲国产精品网站久久| eeuss影院免费92242部| 在线观看免费为成年视频| 亚洲一区二区三区高清| 一级做a爰片久久毛片免费看 | 亚洲欧洲国产综合| a级在线免费观看| 亚洲国产精品一区二区第四页| 亚洲AV无码久久久久网站蜜桃| a毛片视频免费观看影院| 免费人成视频在线观看不卡| 亚洲一区二区三区不卡在线播放| 一个人看的www免费视频在线观看| 免费国产成人高清在线观看麻豆 | 久久亚洲精品无码aⅴ大香| 国产区在线免费观看| 国产成人免费网站在线观看| 亚洲另类视频在线观看| 在线人成精品免费视频|