抽象與封裝是面向?qū)ο蟪绦蛟O(shè)計(jì)的兩個(gè)重要概念。類(lèi)將數(shù)據(jù)以及對(duì)數(shù)據(jù)的操作封裝在一個(gè)抽象數(shù)據(jù)類(lèi)型中,為屬于該類(lèi)的所有對(duì)象提供了同意的抽象描述。
理解抽象與封裝的概念,掌握J(rèn)AVA中的類(lèi)與對(duì)象的應(yīng)用,能夠運(yùn)用面向?qū)ο笏枷脒M(jìn)行類(lèi)的設(shè)計(jì),正確設(shè)計(jì)類(lèi)中的成員方法和成員變量,是我們學(xué)習(xí)的目標(biāo)。
面向?qū)ο笫且环N新型的程序設(shè)計(jì)方法,或者說(shuō)是一種心的程序設(shè)計(jì)規(guī)范,其基本思想是實(shí)用對(duì)象、類(lèi)、繼承、封裝、消息等基本概念來(lái)進(jìn)行程序設(shè)計(jì)。從顯示世界中客觀存在的事務(wù)(即對(duì)象)出發(fā)來(lái)構(gòu)造軟件系統(tǒng),并且在系統(tǒng)構(gòu)建中盡可能運(yùn)行人類(lèi)的自然思維方式。
面向?qū)ο蟮脑O(shè)計(jì)方法用對(duì)象描述事物,而每個(gè)具體的對(duì)象又可以用兩個(gè)特征來(lái)描述:描述事物靜態(tài)屬性所需的數(shù)據(jù)結(jié)構(gòu)以及對(duì)這些數(shù)據(jù)進(jìn)行的有限操作。也就是說(shuō),把數(shù)據(jù)結(jié)構(gòu)和對(duì)數(shù)據(jù)的操作放在一起構(gòu)成一個(gè)整體,才能完整地反應(yīng)實(shí)際問(wèn)題。數(shù)據(jù)結(jié)構(gòu)和對(duì)數(shù)據(jù)的操作實(shí)際上是相互以來(lái)不可分割的整體。
面向?qū)ο蟪绦蛟O(shè)計(jì)具有抽象、封裝、集成和多態(tài)4個(gè)特點(diǎn)。抽象去掉了被研究對(duì)象中與主旨無(wú)關(guān)的次要部分,而僅僅抽取出與研究工作有關(guān)的實(shí)質(zhì)性的內(nèi)容加以考慮。抽象有兩類(lèi):一類(lèi)是過(guò)程抽象,另一類(lèi)是數(shù)據(jù)抽象。
面向?qū)ο蟪绦蛟O(shè)計(jì)強(qiáng)調(diào)數(shù)據(jù)抽象,數(shù)據(jù)抽象把系統(tǒng)總需要處理的數(shù)據(jù)和這些數(shù)據(jù)上的操作結(jié)合在一起,根據(jù)功能、性質(zhì)、作用等因素抽象成不同的抽象數(shù)據(jù)類(lèi)型。每個(gè)抽象數(shù)據(jù)類(lèi)型既包含數(shù)據(jù),又包含針對(duì)這些數(shù)據(jù)的操作,是相對(duì)于過(guò)程抽象更為嚴(yán)格的抽象方法。
封裝
封裝就是利用抽象數(shù)據(jù)類(lèi)型把數(shù)據(jù)和基于數(shù)據(jù)的操作封裝在一起,數(shù)據(jù)被保護(hù)在抽象數(shù)據(jù)類(lèi)型的內(nèi)部,系統(tǒng)的其他部分只有通過(guò)數(shù)據(jù)的操作,才能夠于這個(gè)抽象數(shù)據(jù)類(lèi)型進(jìn)行交互,封裝包含兩層含義。
第一,把對(duì)象的全部屬性及其行為結(jié)合在一起,形成一個(gè)不可分割的獨(dú)立單位(即對(duì)象)。
第二,信息隱蔽,即盡可能隱蔽對(duì)象的內(nèi)部細(xì)節(jié),對(duì)外形成一個(gè)邊界(或者說(shuō)形成一道屏障),只保留有限的對(duì)外接口,使之與外部發(fā)生聯(lián)系。
封裝的原則在軟件上的反應(yīng)是:對(duì)象以外的部分不能隨意存取對(duì)象的內(nèi)部數(shù)據(jù)(屬性),從而有效地避免了外部錯(cuò)誤對(duì)他的“交叉感染”,使軟件錯(cuò)誤能夠局部化,大大減少查錯(cuò)和排錯(cuò)難度。
在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,抽象數(shù)據(jù)類(lèi)型是用“類(lèi)”這種面向?qū)ο蠊ぞ弑硎镜模總€(gè)類(lèi)里都防撞了相關(guān)的數(shù)據(jù)和操作。封裝性降低了程序開(kāi)發(fā)過(guò)程的復(fù)雜性,提高了效率和質(zhì)量,保證了數(shù)據(jù)的完整性和安全性。同時(shí),封裝性提高了抽象數(shù)據(jù)類(lèi)型的可重用性,使抽象數(shù)據(jù)類(lèi)型稱為一個(gè)結(jié)構(gòu)完整、能夠自行管理的有機(jī)整體。
類(lèi)
把眾多的事物歸納、劃分成一些類(lèi),是人類(lèi)在認(rèn)識(shí)客觀世界時(shí)經(jīng)常采用的思維方法。分類(lèi)的原則是抽象。類(lèi)是一組對(duì)象的集合,它為屬于該類(lèi)的所有對(duì)象提供了統(tǒng)一的抽象描述,其內(nèi)部包括屬性和服務(wù)兩個(gè)主要部分。在面向?qū)ο蟮木幊陶Z(yǔ)言中,類(lèi)是一個(gè)獨(dú)立的程序單位行為。類(lèi)的實(shí)例化結(jié)果就是對(duì)象,而對(duì)一類(lèi)對(duì)象的抽象就是類(lèi)。
類(lèi)的定義
類(lèi)是JAVA的核心和本質(zhì),想要在JAVA程序中實(shí)現(xiàn)的每個(gè)概念,都必須封裝自愛(ài)類(lèi)中。類(lèi)是具有共同屬性和行為的對(duì)象的抽象,屬性描述了對(duì)象的狀態(tài),以數(shù)據(jù)的形式存在,在JAVA面向?qū)ο蟪绦蛟O(shè)計(jì)中又貝稱為變量。行為描述了對(duì)數(shù)據(jù)進(jìn)行的操作,可引起對(duì)象狀態(tài)的改變。在JAVA面向?qū)ο蟪绦蛟O(shè)計(jì)中貝稱為方法。
JAVA中類(lèi)的實(shí)現(xiàn)包括兩個(gè)部分:類(lèi)頭和類(lèi)體。類(lèi)頭定義的格式如下:
[類(lèi)定義修飾符] class <類(lèi)名> [extends <父類(lèi)名>] [implements <接口列表>]
類(lèi)的定義主要包括關(guān)鍵詞 class 和類(lèi)名。類(lèi)名是JAVA語(yǔ)言合法的標(biāo)識(shí)符,類(lèi)名一般具有一定的含義。其中,CLASS為定義類(lèi)的關(guān)鍵字,extends是用于繼承的關(guān)鍵字,implements是用于實(shí)現(xiàn)接口的關(guān)鍵字,有關(guān)類(lèi)的修飾符后面將詳細(xì)闡述。
類(lèi)體是類(lèi)的主體部分,它包含了所有實(shí)現(xiàn)類(lèi)功能的JAVA語(yǔ)言程序代碼,包括成員變量和成員方法。JAVA類(lèi)除了繼承它的父類(lèi)中的變量和方法外,一般仍會(huì)在類(lèi)體中明確定義自己的變量和方法。程序中,變量說(shuō)明應(yīng)放在定義之前。類(lèi)體要用{}括起來(lái)。類(lèi)體的格式如下:
class <類(lèi)名>{
[變量修飾符] <變量?jī)?nèi)省> <變量名>
[方法修飾符] <方法返回值類(lèi)型> <方法名>([<參數(shù)列表>]){
方法體
}
}
其中,變量名是JAVA語(yǔ)言中的合法標(biāo)識(shí)符,變量的類(lèi)型可以是JAVA給定的任意數(shù)據(jù)類(lèi)型或者用戶自定義類(lèi)。用于說(shuō)明變量和方法的訪問(wèn)權(quán)限等屬性。
一個(gè)簡(jiǎn)單的學(xué)生類(lèi):
//**********Student.java*********
//學(xué)生類(lèi)的定義
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
public class Strdent{
/*類(lèi)成員的定義*/
private String name; //成員變量
private String sex; //成員變量
rivate int number; //成員變量
void setValue(String a, String b, int c)//成員方法
{
name = a;
sex = b;
number = c;
}
public int getNumber() //成員方法
{
return number;
}
public static void main(String args[]) //成員方法
{
//打印輸出一行字符
System.out.println("這是一個(gè)學(xué)生類(lèi)的定義!");
}
}// Student 類(lèi)結(jié)束
//代表JAV語(yǔ)言中的單行注釋。
/* */ 之間的部分是多行注釋。
類(lèi)的修飾符
類(lèi)的修飾符說(shuō)明類(lèi)的性質(zhì)和訪問(wèn)權(quán)限,分為訪問(wèn)控制符和非訪問(wèn)控制符,包括
public 、protected 、 private 、abstract 和 final 。
1. public , protected 和 private
public , protected 和 private 說(shuō)明類(lèi)的訪問(wèn)權(quán)限,屬于訪問(wèn)控制符。
用public修飾的類(lèi),不僅能貝同一包中其他類(lèi)訪問(wèn),還能貝包之外的類(lèi)和對(duì)象使用。
protected 修飾的類(lèi)為保護(hù)類(lèi),可貝同包類(lèi)和異包子類(lèi)訪問(wèn)。
private 修飾符的類(lèi)為似有類(lèi),外界無(wú)法訪問(wèn)。
共有類(lèi)的定義。
//*******TestPublic.java*******
//共有類(lèi)的定義
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
public class TestPublic
{
/*每個(gè)類(lèi)的main()方法是該程序的入口,而包含main方法的類(lèi)是程序的主類(lèi)。
main()方法的形式是 public static void main(String args[]) */
public static void main(String args[])
{
System.out.println("這是一個(gè)共有類(lèi)");
}
}
下面定義一個(gè)名為T(mén)estProtectedAndPrivate的類(lèi)來(lái)測(cè)試保護(hù)類(lèi)和似有類(lèi)。
保護(hù)類(lèi)和似有類(lèi)的定義:
//*************TestProtectedAndPrivate.java**********
//保護(hù)類(lèi)和似有類(lèi)的定義
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
public class TestProtectedAndPrivate{
//主方法
public static void main(String args[]){
//分別創(chuàng)建保護(hù)類(lèi)和似有類(lèi)的對(duì)象t1和t2
TestProtected t1 = new TestProtected();
TestPrivate t2 = new TestPrivate();
//打印輸出兩行字符
System.out.println(t1.toString());
System.out.println(t2.toString());
}
protected static class TestProtected //保護(hù)類(lèi)
{
public String toString(){
return "保護(hù)類(lèi)的定義:作為潛逃類(lèi)的內(nèi)部類(lèi)";
}
}
private static class TestPrivate //似有類(lèi)
{
public string toString(){
return "私有類(lèi)的定義:作為嵌套類(lèi)的內(nèi)部類(lèi)";
}
}
} // TestProtectedAndPrivate 類(lèi)結(jié)束
aabstract
abstract 說(shuō)明一個(gè)類(lèi)為抽象類(lèi),所謂抽象類(lèi)是指不能直接實(shí)例化對(duì)象的類(lèi)。如果一個(gè)抽象類(lèi)貝說(shuō)明了,則這個(gè)類(lèi)中將包括一個(gè)或幾個(gè)抽象方法。所謂抽象方法是指該方法只有方法說(shuō)明卻沒(méi)有方法體,即沒(méi)有具體實(shí)現(xiàn)的代碼。抽象類(lèi)本身不具備實(shí)際功能,它只用于衍生子類(lèi)。定義抽象類(lèi)和抽象方法的目的是建立抽象模型。抽象類(lèi)中不一定包含抽象方法,但一旦某個(gè)類(lèi)中說(shuō)明了抽象方法,該類(lèi)必須說(shuō)明為抽象類(lèi)。
不包含抽象方法的抽象類(lèi)的定義。
//*************TestAbstract.java*************
//不包含抽象方法的抽象類(lèi)
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
public abstract class TestAbstract{
//該類(lèi)不包含抽象方法
//主方法
public static void main(String args]){
//打印輸出兩行字符
System.out.println("這是一個(gè)不包含抽象方法的抽象類(lèi)!");
System.out.println("抽象類(lèi)不能創(chuàng)建對(duì)象!");
}
} // TestAbstract 類(lèi)結(jié)束
包含抽象方法的抽象類(lèi)的定義。
//********** Mankind.java **********
//包含抽象方法的抽象類(lèi)
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
public abstract class Mankind{
//定義4個(gè)抽象方法
public abstract void closing();
public abstract void food();
public abstract void shelter();
public abstract void transportation();
//主方法
public static void main(String args[]){
//打印輸出兩行字符
System.out.println("這是一個(gè)包含抽象方法的抽象類(lèi)");
System.out.println("抽象方法沒(méi)有方法體");
}
}// Mankind 類(lèi)結(jié)束
final
final 修飾的類(lèi)又稱為最終類(lèi),是指該類(lèi)不能被繼承,不能再有子類(lèi)。它的目的是為了避免盲目繼承。一個(gè)final類(lèi)無(wú)法貝繼承,意味著此類(lèi)在一個(gè)繼承樹(shù)中是一個(gè)葉子類(lèi),并且此類(lèi)的設(shè)計(jì)已貝認(rèn)為很具體而不需要進(jìn)行修改或擴(kuò)展。對(duì)于final類(lèi)中的成員變量,可以定義其為final,也可以不是final。而對(duì)于方法,由于所屬類(lèi)為final的關(guān)系,自然也就成了final類(lèi)型。也可以明確地給final類(lèi)中的方法加上一個(gè)final關(guān)鍵字。下面定義一個(gè)名為T(mén)estFinal的最終類(lèi)。
//************* TestFinal.java ***************
//最終類(lèi)的定義
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
public final class TestFinal
{
//主方法
public static void main(String args[]){
//打印輸出一行字符
System.out.println("這是一個(gè)最終類(lèi),不能被繼承");
}
}//TestFinal類(lèi)結(jié)束
因?yàn)槌橄箢?lèi)的目的就是為了被繼承,而最終類(lèi)的目的是不讓其貝繼承,所以一個(gè)類(lèi)是不能用 abstract 和 final 同時(shí)修飾的。
對(duì)象
對(duì)象是具有某些特俗屬性(數(shù)據(jù))和行為方式(操作)的實(shí)體。對(duì)象可以是有生命的個(gè)體,比如一個(gè)人或一只老虎;還可以是無(wú)生命的個(gè)體,比如一輛汽車(chē)或一臺(tái)計(jì)算機(jī);也可以是一個(gè)抽象的概念,如天氣的變化或鼠標(biāo)產(chǎn)生的事件。對(duì)象有兩個(gè)特征:屬性(property)和行為(Behavior)。例如,一個(gè)人的屬性有姓名、性別、年齡、身高、體重等;行為有唱歌、打球、騎車(chē)和學(xué)習(xí)等。
類(lèi)是一個(gè)抽象的概念,而對(duì)象是一個(gè)具體的概念,是類(lèi)實(shí)例化的結(jié)果。對(duì)象通過(guò)消息傳遞來(lái)進(jìn)行交互。消息傳遞即激活指定的某個(gè)對(duì)象的方法以改變其狀態(tài)或讓它產(chǎn)生一定的行為。
對(duì)象的生命與引用
同基本內(nèi)置類(lèi)型一樣,為了聲明對(duì)象,首先必須寫(xiě)出類(lèi)型名,然后寫(xiě)出該類(lèi)型的所有變量的名字,中間用逗號(hào)隔開(kāi)。下面舉例說(shuō)明怎樣生命一個(gè)類(lèi)的對(duì)象:
Student s1, s2, s3;
上面的生命表示s1\s2\s3是 Student 類(lèi)型的引用變量,可以用來(lái)引用Student型的對(duì)象。引用變量的值將對(duì)應(yīng)一個(gè)內(nèi)存地址,這個(gè)地址標(biāo)識(shí)的空間用來(lái)存放一個(gè)Student對(duì)象。
聲明對(duì)象的引用變量,并不等于創(chuàng)建對(duì)象,當(dāng)然更沒(méi)有為對(duì)象分配存儲(chǔ)空間。這些需要通過(guò) new 關(guān)鍵詞和對(duì)引用變量的賦值才能實(shí)現(xiàn)。
創(chuàng)建對(duì)象與定義構(gòu)造方法
在JAVA語(yǔ)言中,一個(gè)JAVA對(duì)象是類(lèi)的一個(gè)實(shí)力,創(chuàng)建對(duì)象的過(guò)程是對(duì)類(lèi)的實(shí)例化過(guò)程,實(shí)例化對(duì)象就是創(chuàng)建一個(gè)對(duì)象。實(shí)例化對(duì)象意味著給對(duì)象分配必要的存儲(chǔ)空間,用來(lái)保存對(duì)象的變量和方法大媽。new 運(yùn)算符用于創(chuàng)建一個(gè)類(lèi)的實(shí)例并返回對(duì)象的引用,即用來(lái)實(shí)現(xiàn)對(duì)象的實(shí)例化。一般格式為:
<類(lèi)名> <對(duì)象名> = new <類(lèi)名>(<參數(shù)列表>);
創(chuàng)建對(duì)象與生命基本數(shù)據(jù)類(lèi)型的變量相似,首先說(shuō)明新建對(duì)象所屬的類(lèi)名,然后說(shuō)明該對(duì)象名,賦值號(hào)左邊的NEW 關(guān)鍵字是用于為新建對(duì)象開(kāi)辟內(nèi)存空間的運(yùn)算符。與變量相比,對(duì)象占用的內(nèi)存空間要大得多,因?yàn)閷?duì)象既包含變量又包含方法,多數(shù)情況下,變量與方法還不止一個(gè)。例如前面定義的學(xué)生類(lèi) Strdent,假設(shè)有一個(gè)對(duì)象s1,則它就有3個(gè)屬性和2個(gè)方法: s1.name ,s1.sex, s1.number, s1.setValue(), s1.getNumber() 。這些變量和方法保存在一塊內(nèi)存中,這塊內(nèi)存就是對(duì)象s1 所占用的內(nèi)存。如果在新建另一個(gè) Strdent類(lèi)的對(duì)象 s2,則s2對(duì)象將在內(nèi)存中擁有自己的與s1對(duì)象不同的位置相同大小的內(nèi)存空間。
創(chuàng)建對(duì)象的同時(shí)要調(diào)用這個(gè)對(duì)象的構(gòu)造方法完成對(duì)象的初始化工作,JAVA語(yǔ)言中每一個(gè)類(lèi)都有構(gòu)造方法,該方法是一種特殊的方法,其特殊性主要體現(xiàn)在以下幾個(gè)方面。
(1) 構(gòu)造方法的名稱與類(lèi)的名稱相同。
(2) 構(gòu)造方法不返回任何數(shù)據(jù)類(lèi)型,也就沒(méi)有返回值。
(3) 構(gòu)造方法的修飾符只能是訪問(wèn)修飾符,即 public ,private,protected 中的任一個(gè)。
(4) 構(gòu)造方法只能由 new 運(yùn)算符調(diào)用,一般不能由編程人員顯式地直接調(diào)用。
(5) 構(gòu)造方法不能從父類(lèi)中繼承。而在構(gòu)造方法中可以調(diào)用但前父類(lèi)和其父類(lèi)的另一個(gè)構(gòu)造方法,調(diào)用語(yǔ)句必須是構(gòu)造方法的第一條語(yǔ)句。使用當(dāng)前類(lèi)的構(gòu)造方法用this來(lái)引用,使用其父類(lèi)的構(gòu)造方法用 super 來(lái)引用,在構(gòu)造方法的實(shí)現(xiàn)中,可以進(jìn)行方法的重載。
下面定義一個(gè) Student 類(lèi),該類(lèi)具有兩個(gè)構(gòu)造方法,方法的名稱都是 Student,與類(lèi)名相同。
public class Student{
//成員變量
private String name;
private String sex;
private int number;
//成員方法
Student() //構(gòu)造方法
{
name = "NO name";
sex = "unknown";
number = 0;
}
Student(String a, String b, int c)//構(gòu)造方法
{
name = a;
sex = b;
number = c;
}
}// Student 類(lèi)結(jié)束
構(gòu)造方法的重載。
//************* TestConstructor.java ***************
//構(gòu)造方法的重載
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
class Constructor{
//成員變量
private int x;
private double y;
//沒(méi)有參數(shù)的構(gòu)造方法
Constructor()
{
x = 0;
y = 0.0;
}
//一個(gè)參數(shù)的構(gòu)造方法
Constructor(int x){
this.x = x; //使用 this 關(guān)鍵字標(biāo)識(shí)成員變量,以區(qū)別于同名參數(shù)
}
//一個(gè)參數(shù)的構(gòu)造方法,參數(shù)類(lèi)型于前一個(gè)構(gòu)造方法不同
Constructor(double y){
this.y = y;
}
//兩個(gè)參數(shù)的構(gòu)造方法
Constructor(int x, double y){
this.x = x;
this.y = y;
}
// print() 方法顯示成員變量
void print()
{
System.out.println("x=" +x+" y="+y);
}
} // Constructor 類(lèi)結(jié)束
// ConstructorTest 類(lèi)
public class TestConstructor
{
//主方法
public static void main(String args[]){
//創(chuàng)建 Constructor 類(lèi)的對(duì)象 c1 c2 c3 c4 分別使用了不同的構(gòu)造方法
Constructor c1 = new Constructor();
Constructor c2 = new Constructor(53);
Constructor c3 = new Constructor(6.98);
Constructor c4 = new Constructor(5,7.8);
//在屏幕上輸出
c1.print();
c2.print();
c3.print();
c4.print();
}
} // TestConstructor 類(lèi)結(jié)束
對(duì)象的使用
通過(guò)運(yùn)算符“.”可以實(shí)現(xiàn)對(duì)對(duì)象中成員變量的訪問(wèn)和成員方法的調(diào)用。可以通過(guò)設(shè)定成員變量和成員方法訪問(wèn)權(quán)限來(lái)限制對(duì)它的訪問(wèn)。
調(diào)用對(duì)象的成員變量的一般格式為:
<對(duì)象名>.<成員變量名>
其中,對(duì)象名是一個(gè)已生成的對(duì)象,也可以是能生成對(duì)象的表達(dá)式。
例如:
s1.name = "李明";
int num = new Student().number;
調(diào)用對(duì)象的成員方法的一般格式為:
<對(duì)象名>.<成員方法名>([<參數(shù)列表>])
其中,參數(shù)列表是可選項(xiàng)。在進(jìn)行對(duì)象的方法引用時(shí),方法中參數(shù)的個(gè)數(shù)、參數(shù)的數(shù)據(jù)類(lèi)型與原方法中定義的要一致,否則編譯器會(huì)出錯(cuò)。
對(duì)象的使用示例。
//************** Student2.java ***************
//對(duì)象的使用
import java.ioo.*;
public class Student2{
private String name; //姓名
private String sex; //性別
private int number; //學(xué)號(hào)
Student2() //無(wú)參構(gòu)造方法
{
name = "No name";
sex = "unknown";
number = 0;
}
Student2(String a, String b, int c){
name = a;
sex = b;
number = c;
}
public void setName(String a){
name = a;
}
public void setSex(String b){
sex = b;
}
public void setNumber(int c){
number = c;
}
public String getName(){
return name;
}
public String getSex(){
return sex;
}
public int getNumber(){
return number;
}
public static void main(String args[]){
Student2 s1 = new Student2();
Student2 s2 = new Student2("李明","男",102305);
System.out.println("對(duì)象的使用");
System.out.println("-------------------------");
System.out.println("第一個(gè)學(xué)習(xí)的姓名:"+s1.getName());
System.out.println("第一個(gè)學(xué)生的性別:"+s1.getSex());
System.out.println("第一個(gè)學(xué)生的學(xué)號(hào):"+s1.getNumber());
System.out.println("-------------------------");
System.out.pringln("第二個(gè)學(xué)生的姓名:"+s2.getName());
System.out.println("第二個(gè)學(xué)生的性別:"+s2.getSex());
System.out.println("第二個(gè)學(xué)生的學(xué)號(hào):"+s2.getNumber());
}
} // Student2 類(lèi)結(jié)束
在定義一個(gè)類(lèi)時(shí),類(lèi)中的成員變量也可以是一個(gè)類(lèi),例2-9中包含2個(gè)類(lèi):Data類(lèi)和Person類(lèi),Person類(lèi)的成員變量birth為Data類(lèi)型。
//************* Person.java **************
//對(duì)象作為類(lèi)的成員變量
import java.io.*;
public class Date
{
int year;
int month;
int day;
Date(int year, int month, int day){
this.year = year; //用關(guān)鍵字this標(biāo)識(shí)類(lèi)成員變量,一面與同名參數(shù)混淆
this.month = month;
this.day = day;
}
void showDate(){
System.out.println(year+","+month+","+day);
}
}//Date類(lèi)結(jié)束
public class Person
{
private String name;
private String sex;
private Date birth; //對(duì)象作為類(lèi)的成員變量,默認(rèn)初始值為null
void setValue(String s1, String s2, int y, int m, int d){
name = s1;
sex = s2;
birth = new Date(y,m,d);
}
void showValue(){
System.out.println("姓名:"+name);
System.out.println("性別:"+sex);
System.out.print("出生年月日:");
birth.showDate();
}
public static void main(String args[]){
Person per = new Person();
per.setValue("李明","男",1975,7,8);
per.showValue();
}
}//Person 類(lèi)結(jié)束
finalize() 是銷(xiāo)毀一個(gè)對(duì)象用的
成員變量
成員變量是類(lèi)和對(duì)象的數(shù)據(jù)屬性,其本身也有一些修飾符:訪問(wèn)控制符 public private protected 以及非訪問(wèn)控制符 static final transient volatile.這里主要探討常用的static 和final這兩個(gè)非訪問(wèn)控制符。
靜態(tài)變量
使用關(guān)鍵字static 生命的成員變量稱為靜態(tài)變量。靜態(tài)變量也稱類(lèi)變量(class variable),它與類(lèi)關(guān)聯(lián),由類(lèi)鐘的所有對(duì)象共享。無(wú)論生成多少個(gè)這種類(lèi)的對(duì)象,靜態(tài)變量都只有一份,并且即使沒(méi)有生成任何對(duì)象,這種變量也存在。靜態(tài)變量之所以稱為類(lèi)變量,是因?yàn)檫@種變量是屬于相應(yīng)類(lèi)的,而不是屬于特定對(duì)象的,他們?cè)谠擃?lèi)的全部對(duì)象中共享。靜態(tài)變量可以由任何該類(lèi)的對(duì)象和類(lèi)引用,當(dāng)某個(gè)對(duì)象修改了靜態(tài)變量的值后,其他對(duì)象在訪問(wèn)靜態(tài)變量時(shí),取得的將是改變后的新值。
相對(duì)地,沒(méi)有用static修飾的普通成員變量稱為實(shí)例變量(instance variable)。在類(lèi)中,實(shí)例變量與每個(gè)對(duì)象都唯一關(guān)聯(lián),每個(gè)類(lèi)的對(duì)象將擁有自己的一份實(shí)例變量的復(fù)制,并且賦予他自己的值。實(shí)例變量使一個(gè)對(duì)象與其他對(duì)象相互區(qū)別,使對(duì)象具有自己的個(gè)性。
下面定義一個(gè)學(xué)生 Student 類(lèi),其中包含2個(gè)靜態(tài)變量和3個(gè)實(shí)例變量。
public class Student
{
static String school = "黑龍江科技學(xué)院";
static String classNumber;
//實(shí)例變量
String name;
string sex;
int number;
Student(){
name = "No name";
sex = "unknown";
number = 0;
}
Strdent (String a,String b, int c) //構(gòu)造方法
{
name = a;
sex = b;
number = c;
}
}//Student類(lèi)結(jié)束
最終變量
使用關(guān)鍵字final聲明的成員變量稱為最終變量,更確切地說(shuō)是常量。只不過(guò)為他們?nèi)×艘粋€(gè)類(lèi)似變量的標(biāo)識(shí)符名字。用final修飾符聲明常量時(shí),需要說(shuō)明常量的數(shù)據(jù)類(lèi)型并要初始化具體的數(shù)值。另外,因?yàn)樗蓄?lèi)對(duì)象的常量數(shù)據(jù)成員數(shù)值都一樣,為了節(jié)省內(nèi)存控件,常量通常聲明為static。 例如下面球體類(lèi)中的常量PI:
public class Sphere
{
//常量
static final double PI = 3.14;
//變量
double xCenter;
double yCenter;
double zCenter;
double radius;
}// Sphere 類(lèi)結(jié)束
成員方法
成員方法是類(lèi)的行為,標(biāo)志著類(lèi)所具有的功能,是對(duì)類(lèi)中成員變量的操作。JAVA中方法的一般格式如下:
[方法修飾符] [返回值類(lèi)型] <方法名> ([<形式參數(shù)列表>]) [throws <異常列表>]
{
<方法體>
}
成員方法是具有相對(duì)獨(dú)立性的功能模塊,是一個(gè)類(lèi)與外界進(jìn)行通信的接口。成員方法也有一些修飾符:訪問(wèn)修飾符public private procected 和非訪問(wèn)控制符 static abstract final native synchronized 下面分別探討這幾個(gè)非訪問(wèn)控制符
靜態(tài)方法
使用那個(gè)關(guān)鍵字static聲明的成員方法稱為靜態(tài)方法。靜態(tài)方法也稱為類(lèi)方法(class method),它與類(lèi)關(guān)聯(lián),是屬于整個(gè)類(lèi)的,即使類(lèi)中一個(gè)對(duì)象也不存在,也可以執(zhí)行該類(lèi)的類(lèi)方法。正式因?yàn)樵跊](méi)有對(duì)象存在的情況下也可以執(zhí)行類(lèi)方法,因此它只能調(diào)用類(lèi)變量,即靜態(tài)方法只能處理靜態(tài)變量,而不能處理類(lèi)中的實(shí)例變量。很明顯,實(shí)例變量是屬于某個(gè)特定對(duì)象的,如果對(duì)象不存在,實(shí)例變量也就不存在,這時(shí)用類(lèi)方法去操縱和處理一個(gè)可能不存在的變量肯定會(huì)出問(wèn)題。實(shí)際上,JAVA編譯器根本就不允許做這樣的嘗試。如果在一個(gè)類(lèi)方法中引用了一個(gè)實(shí)例變量,系統(tǒng)將拒絕編譯,從而出現(xiàn)出錯(cuò)信息。
相對(duì)地,未用static 修飾的普通成員方法稱為實(shí)例方法(instance method)。實(shí)例方法只能針對(duì)特定的對(duì)象執(zhí)行,因此如果任何對(duì)象都不存在,也就沒(méi)有可以執(zhí)行的實(shí)例方法。
靜態(tài)方法實(shí)例:
//************** StaticFunction.java ***************
//靜態(tài)方法
import java.io.*; //加載系統(tǒng)輸入輸出類(lèi)
public class StaticFunction
{
static int classVariable; //靜態(tài)變量,即類(lèi)變量
int instanceVariable; //非靜態(tài)變量,即實(shí)例變量
// setClassVariable()方法為靜態(tài)方法,即類(lèi)方法
static void setClassVariable(int i){
//this.classvar = i; 不能使用this
classvariable = i;
//instanceVar=i; 不能訪問(wèn)實(shí)例變量
}
void setInstanceVar(int i){
instanceVariable = i;
classvariable = i;
}
//MAIN方法也為靜態(tài)方法
public static void main(String a[]){
StaticFunction sf = new StaticFunction();
/*
下面的語(yǔ)句不合法,main()方法是類(lèi)方法,不能在類(lèi)方法中直接調(diào)用實(shí)例方法
setInseranceVariable(58);
*/
sf.setInstanceVariable(58);//在類(lèi)方法中只能通過(guò)實(shí)例對(duì)象訪問(wèn)實(shí)例方法
sf.setInstanceVariable(58);
setInstanceVariable(58);
StaticFunction.setClassVariable(55);
System.out.println("靜態(tài)方法中不能直接調(diào)用實(shí)例方法,只能通過(guò)對(duì)象訪問(wèn)實(shí)例方法");
}
}
抽象方法
使用關(guān)鍵字abstract聲明的成員方法稱為抽象方法。抽象方法只有方法頭,沒(méi)有方法體。抽象方法的聲明以一個(gè)分號(hào)結(jié)束。
抽象方法示例。
//*************** AbstractFunction.java**************
//抽象方法
import java.io.*;
abstract class Mankind
{
protected String type; //保護(hù)數(shù)據(jù)成員用于繼承
public abstract void closing(); //抽象方法
public abstract void food(); //抽象方法
public abstract void shelter(); //抽象方法
public abstract void transportation(); //抽象方法
public String toString(){
return "這是一個(gè)"+type;
}
}//Mankind類(lèi)結(jié)束
abstract class people extends Mankind
{
//重寫(xiě)Mankind類(lèi)的抽象方法colsing()
public void closing(){
System.out.println("學(xué)會(huì)穿衣了!");
}
//重寫(xiě)Mankind類(lèi)的抽象方法food()
public void food(){
System.out.println("學(xué)會(huì)吃飯了");
}
}//People 類(lèi)結(jié)束
class Person extends People{
//重寫(xiě)People類(lèi)的抽象方法shelter()
public void shelter(){
System.out.println("蓋房子用來(lái)居住");
}
//重寫(xiě)people類(lèi)的抽象方法transportation()
public void transportation(){
System.out.println("使用交通工具出行");
}
//構(gòu)造方法
public Person(String aType){
type = new String(aType);
}
}// Person類(lèi)結(jié)束
public class AbstractFunction{
//AbstractFunction類(lèi)的主方法
public static void main(String args[]){
System.out.println("不能創(chuàng)建抽象類(lèi)Mankind和People的對(duì)象!");
System.out.println("");
Person man = new Person("男人");
Person woman = new Person("女人");
System.out.println(man);
man.closing();
man.food();
man.shelter();
man.transportation();
System.out.println(" ");
System.out.println(woman);
woman.closing();
woman.food();
women.transportation();
}
}//AbstractFunction 類(lèi)結(jié)束
最終方法
使用關(guān)鍵字final聲明的成員方法稱為最終方法。最終方法的功能和內(nèi)部語(yǔ)句不能在被更改,也就是說(shuō)該方法不能貝當(dāng)前類(lèi)的子類(lèi)重新定義。最終方法使得子類(lèi)不能重新定義與父類(lèi)同名的方法,而只能使用從負(fù)累繼承來(lái)的方法,從而防止了子類(lèi)對(duì)父類(lèi)一些方法的錯(cuò)誤定義,保證了程序的安全性和正確性。
本地方法
。。。。。。。。。。。。。。