java之七 高级类设计
| ? ? ? ? ? ? ? ? ? | ? |
|
有時(shí)你希望定義一個(gè)類成員,使它的使用完全獨(dú)立于該類的任何對(duì)象。通常情況下,類成員必須通過(guò)它的類的對(duì)象訪問(wèn),但是可以創(chuàng)建這樣一個(gè)成員,它能夠被它自己使用,而不必引用特定的實(shí)例。在成員的聲明前面加上關(guān)鍵字static(靜態(tài)的)就能創(chuàng)建這樣的成員。
如果一個(gè)成員被聲明為static,它就能夠在它的類的任何對(duì)象創(chuàng)建之前被訪問(wèn),而不必引用任何對(duì)象。你可以將方法和變量都聲明為static。static成員的最常見(jiàn)的例子是main( )。因?yàn)樵诔绦蜷_(kāi)始執(zhí)行時(shí)必須調(diào)用main(),所以它被聲明為static。
聲明為static的變量實(shí)質(zhì)上就是全局變量。當(dāng)聲明一個(gè)對(duì)象時(shí),并不產(chǎn)生static變量的拷貝,而是該類所有的實(shí)例變量共用同一個(gè)static變量。
聲明為static的方法有以下幾條限制:
· 它們僅能調(diào)用其他的static方法。
· 它們只能訪問(wèn)static數(shù)據(jù)。
· 它們不能以任何方式引用this或super(關(guān)鍵字super與繼承有關(guān),在下一章中描述)。?
如果你需要通過(guò)計(jì)算來(lái)初始化你的static變量,你可以聲明一個(gè)static塊,static塊僅在該類被加載時(shí)執(zhí)行一次。 下面的例子顯示的類有一個(gè)static方法, 一些static變量, 以及一個(gè)static初始化塊:
// Demonstrate static variables,methods,and blocks.
class UseStatic {
? static inta = 3;
? static intb;
?
? static voidmeth(int x) {
System.out.println("x = " + x);
System.out.println("a = " + a);
System.out.println("b = " + b);
? }
?
? static {
System.out.println("Static block initialized.");
b = a * 4;
? }
?
? publicstatic void main(String args[]) {
meth(42);
? }
}
一旦UseStatic類被裝載,所有的static語(yǔ)句被運(yùn)行。首先,a被設(shè)置為3,接著static塊執(zhí)行(打印一條消息),最后,b被初始化為a*4或12。然后調(diào)用main(),main()調(diào)用meth(),把值42傳遞給x。3個(gè)println ( )語(yǔ)句引用兩個(gè)static變量a和b,以及局部變量x 。
注意:在一個(gè)static方法中引用任何實(shí)例變量都是非法的。
下面是該程序的輸出:
Static block initialized.
x = 42
a = 3
b = 12
在定義它們的類的外面,static方法和變量能獨(dú)立于任何對(duì)象而被使用。這樣,你只要在類的名字后面加點(diǎn)號(hào)運(yùn)算符即可。例如,如果你希望從類外面調(diào)用一個(gè)static方法,你可以使用下面通用的格式:
classname.method( )
這里,classname? 是類的名字,在該類中定義static方法??梢钥吹?#xff0c;這種格式與通過(guò)對(duì)象引用變量調(diào)用非static方法的格式類似。一個(gè)static變量可以以同樣的格式來(lái)訪問(wèn)——類名加點(diǎn)號(hào)運(yùn)算符。這就是Java如何實(shí)現(xiàn)全局功能和全局變量的一個(gè)控制版本。
下面是一個(gè)例子。在main()中,static方法callme()和static變量b在它們的類之外被訪問(wèn)。
class StaticDemo {
? static inta = 42;
? static intb = 99;
? static voidcallme() {
System.out.println("a = " + a);
? }
}
?
class StaticByName {
? publicstatic void main(String args[]) {
StaticDemo.callme();
System.out.println("b = " +StaticDemo.b);
? }
}
下面是該程序的輸出:
a = 42
b = 99
|
一個(gè)變量可以聲明為final, 這樣做的目的是阻止它的內(nèi)容被修改。這意味著在聲明final變量的時(shí)候,你必須初始化它(在這種用法上,final類似于C/C++中的const)。例如:
final int FILE_NEW = 1;
final int FILE_OPEN = 2;
final int FILE_SAVE = 3;
final int FILE_SAVEAS = 4;
final int FILE_QUIT = 5;
你的程序的隨后部分現(xiàn)在可以使用 FILE_OPEN等等,就好像它們是常數(shù),不必?fù)?dān)心它們的值會(huì)被改變。
為final變量的所有的字符選擇大寫是一個(gè)普遍的編碼約定。聲明為final的變量在實(shí)例中不占用內(nèi)存。這樣,一個(gè)final變量實(shí)質(zhì)上是一個(gè)常數(shù)。
關(guān)鍵字final也可以被應(yīng)用于方法,但是它的意思和它被用于變量實(shí)質(zhì)上是不同的。final的第二種用法將在下一章描述繼承時(shí)解釋。
?
?
|
Enum作為Sun全新引進(jìn)的一個(gè)關(guān)鍵字,看起來(lái)很象是特殊的class, 它也可以有自己的變量,可以定義自己的方法,可以實(shí)現(xiàn)一個(gè)或者多個(gè)接口。當(dāng)我們?cè)诼暶饕粋€(gè)enum類型時(shí),我們應(yīng)該注意到enum類型有如下的一些特征。
1.它不能有public的構(gòu)造函數(shù),這樣做可以保證客戶代碼沒(méi)有辦法新建一個(gè)enum的實(shí)例。
2.所有枚舉值都是public , static , final的。注意這一點(diǎn)只是針對(duì)于枚舉值,我們可以和在普通類里面定義變量一樣定義其它任何類型的非枚舉變量,這些變量可以用任何你想用的修飾符。
3.Enum默認(rèn)實(shí)現(xiàn)了java.lang.Comparable接口。
4.Enum覆載了了toString方法,因此我們?nèi)绻{(diào)用Color.Blue.toString()默認(rèn)返回字符串”Blue”.
5.Enum提供了一個(gè)valueOf方法,這個(gè)方法和toString方法是相對(duì)應(yīng)的。調(diào)用valueOf(“Blue”)將返回Color.Blue.因此我們?cè)谧约褐貙憈oString方法的時(shí)候就要注意到這一點(diǎn),一把來(lái)說(shuō)應(yīng)該相對(duì)應(yīng)地重寫valueOf方法。
6.Enum還提供了values方法,這個(gè)方法使你能夠方便的遍歷所有的枚舉值。
7.Enum還有一個(gè)oridinal的方法,這個(gè)方法返回枚舉值在枚舉類種的順序,這個(gè)順序根據(jù)枚舉值聲明的順序而定,這里Color.Red.ordinal()返回0。
1.遍歷所有有枚舉值. 知道了有values方法,我們可以輕車熟路地用ForEach循環(huán)來(lái)遍歷了枚舉值了。
for (Color c: Color.values())
System.out.println(“find value:” + c);
2.在enum中定義方法和變量,比如我們可以為Color增加一個(gè)方法隨機(jī)返回一個(gè)顏色。
public?enum?Color?...{
Red,
Green,
Blue;?
/**//*
*定義一個(gè)變量表示枚舉值的數(shù)目。
*(我有點(diǎn)奇怪為什么sun沒(méi)有給enum直接提供一個(gè)size方法).
*/
private?static?int?number?=?Color.values().length?;
?
/**?*//**
*?隨機(jī)返回一個(gè)枚舉值
@return?a?random?enum?value.?
*/
public?static?Color?getRandomColor()...{
long?random?=?System.currentTimeMillis()?%?number;
switch?((int)?random)...{
case?0:
return?Color.Red;
case?1:
return?Color.Green;
case?2:
return?Color.Blue;
default?:?return?Color.Red;
}?
}
}
可以看出這在枚舉類型里定義變量和方法和在普通類里面定義方法和變量沒(méi)有什么區(qū)別。唯一要注意的只是變量和方法定義必須放在所有枚舉值定義的后面,否則編譯器會(huì)給出一個(gè)錯(cuò)誤。
3.覆載(Override)toString, valueOf方法。
前面我們已經(jīng)知道enum提供了toString,valueOf等方法,很多時(shí)候我們都需要覆載默認(rèn)的toString方法,那么對(duì)于enum我們?cè)趺醋瞿?。其?shí)這和覆載一個(gè)普通class的toString方法沒(méi)有什么區(qū)別。
….
public?String?toString()...{?
switch?(this)...{
case?Red:
return?"Color.Red";
case?Green:
return?"Color.Green";
case?Blue:
return?"Color.Blue";
default:
return?"Unknow?Color";
}
}….
這時(shí)我們可以看到,此時(shí)再用前面的遍歷代碼打印出來(lái)的是
Color.Red
Color.Green
Color.Blue
而不是
Red
Green
Blue.
可以看到toString確實(shí)是被覆載了。一般來(lái)說(shuō)在覆載toString的時(shí)候我們同時(shí)也應(yīng)該覆載valueOf方法,以保持它們相互的一致性。
4.使用構(gòu)造函數(shù)。
雖然enum不可以有public的構(gòu)造函數(shù),但是我們還是可以定義private的構(gòu)造函數(shù),在enum內(nèi)部使用。還是用Color這個(gè)例子。
public?enum?Color?...{
Red("This?is?Red"),
Green("This?is?Green"),
Blue("This?is?Blue");?
private?String?desc;
Color(String?desc)...{
this.desc?=?desc;
}
public?String?getDesc()...{
return?this.desc;
}
}
這里我們?yōu)槊恳粋€(gè)顏色提供了一個(gè)說(shuō)明信息
public?enum?Color?...{
Red?...{?
public?String?toString()...{
return?"Color.Red";
}
},
Green?...{
public?String?toString()...{
return?"Color.Green";
}
},
Blue...{
public?String?toString()...{
return?"Color.Blue";
}
};?
}
, 然后定義了一個(gè)構(gòu)造函數(shù)接受這個(gè)說(shuō)明信息。
要注意這里構(gòu)造函數(shù)不能為public或者protected, 從而保證構(gòu)造函數(shù)只能在內(nèi)部使用,客戶代碼不能new一個(gè)枚舉值的實(shí)例出來(lái)。這也是完全符合情理的,因?yàn)槲覀冎烂杜e值是publicstatic final的常量而已。
5.實(shí)現(xiàn)特定的接口
我們已經(jīng)知道enum可以定義變量和方法,它要實(shí)現(xiàn)一個(gè)接口也和普通class實(shí)現(xiàn)一個(gè)接口一樣,這里就不作示例了。
6.定義枚舉值自己的方法。
前面我們看到可以為enum定義一些方法,其實(shí)我們甚至可以為每一個(gè)枚舉值定義方法。這樣,我們前面覆載 toString的例子可以被改寫成這樣。
從邏輯上來(lái)說(shuō)這樣比原先提供一個(gè)“全局“的toString方法要清晰一些。
總的來(lái)說(shuō),enum作為一個(gè)全新定義的類型,是希望能夠幫助程序員寫出的代碼更加簡(jiǎn)單易懂,個(gè)人覺(jué)得一般也不需要過(guò)多的使用enum的一些高級(jí)特性,否則就和簡(jiǎn)單易懂的初衷想違背了。
?
?
|
從jdk5.0開(kāi)始,import不僅可以導(dǎo)入類,還可以導(dǎo)入靜態(tài)方法和靜態(tài)域。
如果在源文件頂部添加import static java.lang.System.*;
那么就可以使用System類的靜態(tài)方法和靜態(tài)域,而不必加類前綴如:
out.println("hello world"); 相當(dāng)于 System.out.println("helloworld");
exit(0);?相當(dāng)于 System.exit(0);???
靜態(tài)方法導(dǎo)入和導(dǎo)入靜態(tài)域有兩個(gè)實(shí)際的應(yīng)用:
1.算術(shù)函數(shù),對(duì)Math類使用靜態(tài)導(dǎo)入,就能更自然的使用算術(shù)函數(shù)
sqrt(pow(x,2)+pow(y,2));
2.笨重的常量,如果需要使用大量帶有冗長(zhǎng)名字的常量,就應(yīng)該使用靜態(tài)導(dǎo)入
Date d = new Date();
if(d.get(DAY_OF_WEEK) == MONDAY)
? 看起來(lái)比
if(d.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY)
? 清晰
代碼:
import?static?java.lang.Math.pow;??
import?static?java.lang.Math.sqrt;??
import?static?java.lang.System.out;??
import?static?java.util.Calendar.MONDAY;??
??
import?java.util.Date; ??
??
public?class?StaticImportTest?{??
??
????/** ?
?????*?@param?args?
?????*/??
????public?static?void?main(String[]?args)?{??
????????out.println("hello");??
????????int?x?=?5,y=10;??
????????double?d?=?sqrt(pow(x,2)?+?pow(y,2));??
????????out.println(d);??
??????????
????????Date?date?=?new?Date();??
????????if(date.getDay()?==?MONDAY)??
????????????out.println("今天星期1"); ??
????????else{??
????????????out.println("今天星期"+?date.getDay());??
????????}??
????} ??
??
}??
?
?
|
Java語(yǔ)言中答應(yīng)有一種叫做抽象方法的東西,他只是一個(gè)名字沒(méi)有具體的實(shí)現(xiàn)。像是這樣: public abstract void abc();使用了abstract要害字,結(jié)尾用“;”結(jié)束。與前幾節(jié)我們用的方法都是具體方法,是有實(shí)現(xiàn)的。哪怕方法體中什么也不寫public void abc() { } 也是具體方法。
概念:包含一個(gè)或多個(gè)抽象方法的類稱為抽象類。抽象類也必須聲明abstract要害字。抽象類的使用有著一些限制,不能創(chuàng)建抽象類的實(shí)例。假如子類實(shí)現(xiàn)了抽象方法,則可以創(chuàng)建該子類的實(shí)例對(duì)象。要是子類也不實(shí)現(xiàn)的話,這個(gè)子類也是抽象類,也不能創(chuàng)建實(shí)例。
接口是什么東西呢?接口是比抽象類更抽象的類。舉例: public interface Name { }接口里面的方法全都是抽象的,里面的變量全都是final的常量,而且實(shí)現(xiàn)接口的類必須將所有的抽象方法全部實(shí)現(xiàn)。抽象類里也可以有具體的方法。所以說(shuō),接口是最抽象的,其次是抽象類,而具體類本身就是對(duì)現(xiàn)實(shí)世界的抽象。軟件開(kāi)發(fā)本身就是將現(xiàn)實(shí)世界抽象成計(jì)算機(jī)世界。
因?yàn)槌橄箢惡徒涌诒染唧w類抽象,所以使用時(shí)他們總是被繼續(xù)而被實(shí)現(xiàn)的。不過(guò)繼續(xù)他們的類不只是一個(gè),有很多類實(shí)現(xiàn)他們的抽象方法。一個(gè)方法有多種實(shí)現(xiàn)方式,這里用到了OOP中的多態(tài)性。這使得設(shè)計(jì)變得非常清楚。因?yàn)榛愂浅橄箢惢蚴墙涌谧鲆粋€(gè)描述,底下繼續(xù)的類有若干個(gè),我們只需要對(duì)接口或抽象類操作,也用不著管有多少個(gè)實(shí)現(xiàn)。假如是多人共同開(kāi)發(fā)的項(xiàng)目的話,是非常有意義的。你自己寫個(gè)東西,怎么實(shí)現(xiàn)的也不用告訴別人,別人看個(gè)接口就夠了。
接口的實(shí)現(xiàn)用要害字implement 而不是extends.假如用了extends的那就是繼續(xù)這個(gè)接口。那么那個(gè)子類也是接口,是原來(lái)的子接口。舉個(gè)接口的例子吧:
??? 實(shí)踐:
| //聲明一個(gè)接口 ??? public interface Say { ????? public void sayMessage(); } ??? //兩個(gè)實(shí)現(xiàn)類 ?? public class SayHello implements Say { ????? public void sayMessage() { ????? System.out.println("hello"); ?? }} ?? public class SayHi implements Say { ????? public void sayMessage() { ????? System.out.println("Hi"); ?? }} ?? //這是一個(gè)測(cè)試類 ?? public class TestSay { ????? public static void main(String[] args) { //同樣都是用Say這個(gè)接口類型實(shí)例,卻可以輸出兩個(gè)結(jié)果 ????? Say say = new SayHello(); ????? say.sayMessage(); ????? Say say1 = new SayHi(); ????? say1.sayMessage(); ?? }}? |
接口還有一個(gè)重要的作用,我們?cè)诿嫦驅(qū)ο竽枪?jié)課里提過(guò)一個(gè)概念,java語(yǔ)言中只有單繼續(xù),就是說(shuō)只能從一個(gè)父類繼續(xù)。單繼續(xù)的好處是,一旦繼續(xù)的太多了,改了一個(gè)類子類就都變了。牽一發(fā),而動(dòng)全身。那么假如我們想繼續(xù)多個(gè)父類的特性怎么辦呢?就用接口吧,這個(gè)類可以先繼續(xù)一個(gè)類,再去實(shí)現(xiàn)其它的接口,接口里面都是抽象方法,不會(huì)造成,牽一發(fā),而動(dòng)全身的效應(yīng)。改變多繼續(xù)的特性,也是對(duì)C++語(yǔ)言的一項(xiàng)改進(jìn)。
業(yè)界有一種說(shuō)法說(shuō),與其說(shuō)java是面向?qū)ο缶幊?#xff0c;還不如說(shuō)它是面向接口編程。強(qiáng)調(diào)的方面是接口的抽象描述性。它也是對(duì)C++的一種改進(jìn),C++里面沒(méi)有接口。所以說(shuō)java語(yǔ)言適合多人團(tuán)隊(duì)合作的大項(xiàng)目,看一個(gè)接口就可以了,后面怎么實(shí)現(xiàn)的可以不管。
|
1.??????現(xiàn)實(shí)世界中,公共物品是不是放在大家都能看到或找到的地方;與我們學(xué)的關(guān)鍵字static有什么相似和區(qū)別?
2.??????生活中有些事情是固定不變的,比如法律制度是很多年不變的;這些和我們學(xué)的關(guān)鍵字final有什么相似和區(qū)別的地方?
3.??????如果要建一座大樓,首先要設(shè)計(jì)圖紙;然后把主題的框架搭建好;然后再具體的做進(jìn)一步的細(xì)致工作;最后,一座大樓就建成了;這些步驟與我們軟件工程之前存在什么關(guān)系;哪個(gè)步驟類似于軟件中的設(shè)計(jì)抽象類和接口的過(guò)程?
?
|
?
在本章中,我們主要學(xué)習(xí)了:
?
u??????關(guān)鍵字static、final及相關(guān)應(yīng)用;
u??????Java枚舉類型;
u??????Java靜態(tài)導(dǎo)入
u??????抽象類和接口的使用
?
|
?
英文??????????????????? 全文?????????????????????????? 中文
?
Static???? Static ?????????? 靜態(tài)的
Final???????? Final ??????????? 終結(jié)
Enum????????? Enum????????????? 枚舉
Import????????????????? Import???????????????????????? 導(dǎo)入
?
|
?
總結(jié)人類使用火的手段及火的器具;比如滅火器(經(jīng)常固定位置的)、打火機(jī)(經(jīng)常使用的)、原始人使用的火種(經(jīng)典神圣的)等;可以對(duì)人對(duì)火的形容詞匯做個(gè)總結(jié)歸結(jié)到枚舉類型中;例如:風(fēng)風(fēng)火火、火急火燎等;并對(duì)人類的進(jìn)化做繼承歸納;用面向?qū)ο蠹氨菊驴s寫的知識(shí)寫出相關(guān)代碼;
轉(zhuǎn)載于:https://www.cnblogs.com/mjsn/p/6150932.html
總結(jié)
以上是生活随笔為你收集整理的java之七 高级类设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hive中操作hdfs命令
- 下一篇: lightoj 1020 (博弈水题)