一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

09語法總結(jié) - 方法

 靜聽沙漏 2012-02-14
Java語法總結(jié) - 方法

一、方法的重寫。

1、重寫只能出現(xiàn)在繼承關(guān)系之中。當(dāng)一個(gè)類繼承它的父類方法時(shí),都有機(jī)會(huì)重寫該父類的方法。一個(gè)特例是父類的方法被標(biāo)識(shí)為final。重寫的主要優(yōu)點(diǎn)是能夠定義某個(gè)子類型特有的行為。
class Animal {
public void eat(){
System.out.println ("Animal is eating.");
}
}

class Horse extends Animal{
public void eat(){
System.out.println ("Horse is eating.");
}
}

2、對(duì)于從父類繼承來的抽象方法,要么在子類用重寫的方式設(shè)計(jì)該方法,要么把子類也標(biāo)識(shí)為抽象的。所以抽象方法可以說是必須要被重寫的方法。

3、重寫的意義。
重寫方法可以實(shí)現(xiàn)多態(tài),用父類的引用來操縱子類對(duì)象,但是在實(shí)際運(yùn)行中對(duì)象將運(yùn)行其自己特有的方法。
public class Test {
public static void main (String[] args) {
Animal h = new Horse();
h.eat();
}
}

class Animal {
public void eat(){
System.out.println ("Animal is eating.");
}
}

class Horse extends Animal{
public void eat(){
System.out.println ("Horse is eating.");
}
public void buck(){
}
}

一個(gè)原則是:使用了什么引用,編譯器就會(huì)只調(diào)用引用類所擁有的方法。如果調(diào)用子類特有的方法,如上例的h.buck(); 編譯器會(huì)抱怨的。也就是說,編譯器只看引用類型,而不是對(duì)象類型。

4、重寫方法的規(guī)則。
若想實(shí)現(xiàn)一個(gè)合格重寫方法,而不是重載,那么必須同時(shí)滿足下面的要求!

A、重寫規(guī)則之一:重寫方法不能比被重寫方法限制有更嚴(yán)格的訪問級(jí)別。
(但是可以更廣泛,比如父類方法是包訪問權(quán)限,子類的重寫方法是public訪問權(quán)限。)
比如:Object類有個(gè)toString()方法,開始重寫這個(gè)方法的時(shí)候我們總?cè)菀淄沺ublic修飾符,編譯器當(dāng)然不會(huì)放過任何教訓(xùn)我們的機(jī)會(huì)。出錯(cuò)的原因就是:沒有加任何訪問修飾符的方法具有包訪問權(quán)限,包訪問權(quán)限比public當(dāng)然要嚴(yán)格了,所以編譯器會(huì)報(bào)錯(cuò)的。

B、重寫規(guī)則之二:參數(shù)列表必須與被重寫方法的相同。
重寫有個(gè)孿生的弟弟叫重載,也就是后面要出場(chǎng)的。如果子類方法的參數(shù)與父類對(duì)應(yīng)的方法不同,那么就是你認(rèn)錯(cuò)人了,那是重載,不是重寫。

C、重寫規(guī)則之三:返回類型必須與被重寫方法的返回類型相同。
父類方法A:void eat(){} 子類方法B:int eat(){} 兩者雖然參數(shù)相同,可是返回類型不同,所以不是重寫。
父類方法A:int eat(){} 子類方法B:long eat(){} 返回類型雖然兼容父類,但是不同就是不同,所以不是重寫。

D、重寫規(guī)則之四:重寫方法不能拋出新的異?;蛘弑缺恢貙懛椒暶鞯臋z查異常更廣的檢查異常。但是可以拋出更少,更有限或者不拋出異常。
import java.io.*;
public class Test {
public static void main (String[] args) {
Animal h = new Horse();
try {
h.eat();
}
catch (Exception e) {
}
}
}

class Animal {
public void eat() throws Exception{
System.out.println ("Animal is eating.");
throw new Exception();
}
}

class Horse extends Animal{
public void eat() throws IOException{
System.out.println ("Horse is eating.");
throw new IOException();
}
}
這個(gè)例子中,父類拋出了檢查異常Exception,子類拋出的IOException是Exception的子類,也即是比被重寫的方法拋出了更有限的異常,這是可以的。如果反過來,父類拋出IOException,子類拋出更為寬泛的Exception,那么不會(huì)通過編譯的。
注意:這種限制只是針對(duì)檢查異常,至于運(yùn)行時(shí)異常RuntimeException及其子類不再這個(gè)限制之中。

E、重寫規(guī)則之五:不能重寫被標(biāo)識(shí)為final的方法。

F、重寫規(guī)則之六:如果一個(gè)方法不能被繼承,則不能重寫它。
比較典型的就是父類的private方法。下例會(huì)產(chǎn)生一個(gè)有趣的現(xiàn)象。
public class Test {
public static void main (String[] args) {
//Animal h = new Horse();
Horse h = new Horse();
h.eat();
}
}

class Animal {
private void eat(){
System.out.println ("Animal is eating.");
}
}

class Horse extends Animal{
public void eat(){
System.out.println ("Horse is eating.");
}
}
這段代碼是能通過編譯的。表面上看來違反了第六條規(guī)則,但實(shí)際上那是一點(diǎn)巧合。Animal類的eat()方法不能被繼承,因此Horse類中的eat()方法是一個(gè)全新的方法,不是重寫也不是重載,只是一個(gè)只屬于Horse類的全新的方法!這點(diǎn)讓很多人迷惑了,但是也不是那么難以理解。
main()方法如果是這樣:
Animal h = new Horse();
//Horse h = new Horse();
h.eat();
編譯器會(huì)報(bào)錯(cuò),為什么呢?Horse類的eat()方法是public的??!應(yīng)該可以調(diào)用??!請(qǐng)牢記,多態(tài)只看父類引用的方法,而不看子類對(duì)象的方法!


二、方法的重載。
重載是有好的,它不要求你在調(diào)用一個(gè)方法之前轉(zhuǎn)換數(shù)據(jù)類型,它會(huì)自動(dòng)地尋找匹配的方法。方法的重載是在編譯時(shí)刻就決定調(diào)用哪個(gè)方法了,和重寫不同。最最常用的地方就是構(gòu)造器的重載。

1、基本數(shù)據(jù)類型參數(shù)的重載。
public class Test {
static void method(byte b){
System.out.println ("method:byte");
}
static void method(short s){
System.out.println ("method:short");
}
static void method(int i){
System.out.println ("method:int");
}
static void method(float f){
System.out.println ("method:float");
}
static void method(double d){
System.out.println ("method:double");
}
public static void main (String[] args) {
method((byte)1);
method('c');
method(1);
method(1L);
method(1.1);
method(1.1f);
}
}
輸出結(jié)果:
method:byte
method:int
method:int
method:float
method:double
method:float

可以看出:首先要尋找的是數(shù)據(jù)類型正好匹配方法。如果找不到,那么就提升為表達(dá)能力更強(qiáng)的數(shù)據(jù)類型,如上例沒有正好容納long的整數(shù)類型,那么就轉(zhuǎn)換為float類型的。如果通過提升也不能找到合適的兼容類型,那么編譯器就會(huì)報(bào)錯(cuò)。反正是不會(huì)自動(dòng)轉(zhuǎn)換為較小的數(shù)據(jù)類型的,必須自己強(qiáng)制轉(zhuǎn)換,自己來承擔(dān)轉(zhuǎn)變后果。

char類型比較特殊,如果找不到正好匹配的類型,它會(huì)轉(zhuǎn)化為int而不是short,雖然char是16位的。


2、重載方法的規(guī)則。

A、被重載的方法必須改變參數(shù)列表。
參數(shù)必須不同,這是最重要的!不同有兩個(gè)方面,參數(shù)的個(gè)數(shù),參數(shù)的類型,參數(shù)的順序。

B、被重載的方法與返回類型無關(guān)。
也就是說,不能通過返回類型來區(qū)分重載方法。

C、被重載的方法可以改變?cè)L問修飾符。
沒有重寫方法那樣嚴(yán)格的限制。

D、被重載的方法可以聲明新的或者更廣的檢查異常。
沒有重寫方法那樣嚴(yán)格的限制。

E、方法能夠在一個(gè)類中或者在一個(gè)子類中被重載。


3、帶對(duì)象引用參數(shù)的方法重載。
class Animal {}
class Horse extends Animal{}

public class Test {
static void method(Animal a){
System.out.println ("Animal is called.");
}
static void method(Horse h){
System.out.println ("Horse is called.");
}
public static void main (String[] args) {
Animal a = new Animal();
Horse h = new Horse();
Animal ah = new Horse();

method(a);
method(h);
method(ah);
}
}
輸出結(jié)果是:
Animal is called.
Horse is called.
Animal is called.
前兩個(gè)輸出沒有任何問題。第三個(gè)方法為什么不是輸出“Horse is called.”呢?還是那句老話,要看引用類型而不是對(duì)象類型,方法重載是在編譯時(shí)刻就決定的了,引用類型決定了調(diào)用哪個(gè)版本的重載方法。


4、重載和重寫方法區(qū)別的小結(jié)。
如果能徹底弄明白下面的例子,說明你對(duì)重載和重寫非常了解了,可以結(jié)束這節(jié)的復(fù)習(xí)了。
class Animal {
public void eat(){
System.out.println ("Animal is eating.");
}
}
class Horse extends Animal{
public void eat(){
System.out.println ("Horse is eating.");
}
public void eat(String food){
System.out.println ("Horse is eating " + food);
}
}

public class Test {
public static void main (String[] args) {
Animal a = new Animal();
Horse h = new Horse();
Animal ah = new Horse();

a.eat();
h.eat();
h.eat("apple");
ah.eat();
//a.eat("apple");
//ah.eat("apple");
}
}

四個(gè)輸出分別是什么?被注釋的兩條語句為什么不能通過編譯?
第一條:a.eat(); 普通的方法調(diào)用,沒有多態(tài),沒什么技術(shù)含量。調(diào)用了Animal類的eat()方法,輸出:Animal is eating.
第二條:h.eat(); 普通的方法調(diào)用,也沒什么技術(shù)含量。調(diào)用了Horse類的eat()方法,輸出:Horse is eating.
第三條:h.eat("apple"); 重載。Horse類的兩個(gè)eat()方法重載。調(diào)用了Horse類的eat(String food)方法,輸出:Horse is eating apple
第四條:ah.eat(); 多態(tài)。前面有例子了,不難理解。輸出:Horse is eating.
第五條:a.eat("apple"); 低級(jí)的錯(cuò)誤,Animal類中沒有eat(String food)方法。因此不能通過編譯。
第六條:ah.eat("apple"); 關(guān)鍵點(diǎn)就在這里。解決的方法還是那句老話,不能看對(duì)象類型,要看引用類型。Animal類中沒有eat(String food)方法。因此不能通過編譯。

小結(jié)一下:多態(tài)不決定調(diào)用哪個(gè)重載版本;多態(tài)只有在決定哪個(gè)重寫版本時(shí)才起作用。
重載對(duì)應(yīng)編譯時(shí),重寫對(duì)應(yīng)運(yùn)行時(shí)。夠簡(jiǎn)潔的了吧!


三、構(gòu)造方法。
構(gòu)造方法是一種特殊的方法,沒有構(gòu)造方法就不能創(chuàng)建一個(gè)新對(duì)象。實(shí)際上,不僅要調(diào)用對(duì)象實(shí)際類型的構(gòu)造方法,還要調(diào)用其父類的構(gòu)造方法,向上追溯,直到Object類。構(gòu)造方法不必顯式地調(diào)用,當(dāng)使用new關(guān)鍵字時(shí),相應(yīng)的構(gòu)造方法會(huì)自動(dòng)被調(diào)用。

1、構(gòu)造方法的規(guī)則。
A、構(gòu)造方法能使用任何訪問修飾符。包括private,事實(shí)上java類庫有很多都是這樣的,設(shè)計(jì)者不希望使用者創(chuàng)建該類的對(duì)象。

B、構(gòu)造方法的名稱必須與類名相同。這樣使得構(gòu)造方法與眾不同,如果我們遵守sun的編碼規(guī)范,似乎只有構(gòu)造方法的首字母是大寫的。

C、構(gòu)造方法不能有返回類型。
反過來說,有返回類型的不是構(gòu)造方法
public class Test {
int Test(){
return 1;
}
}
這個(gè)方法是什么東西?一個(gè)冒充李逵的李鬼而已,int Test()和其他任何普通方法沒什么兩樣,就是普通的方法!只不過看起來很惡心,類似惡心的東西在考試卷子里比較多。

D、如果不在類中創(chuàng)建自己的構(gòu)造方法,編譯器會(huì)自動(dòng)生成默認(rèn)的不帶參數(shù)的構(gòu)造函數(shù)。
這點(diǎn)很容易驗(yàn)證!寫一個(gè)這樣簡(jiǎn)單的類,編譯。
class Test {
}
對(duì)生成的Test.class文件反編譯:javap Test,可以看到:
D:"JavaCode"bin>javap Test
Compiled from "Test.java"
class Test extends java.lang.Object{
Test();
}
看到編譯器自動(dòng)添加的默認(rèn)構(gòu)造函數(shù)了吧!

E、如果只創(chuàng)建了帶參數(shù)的構(gòu)造方法,那么編譯器不會(huì)自動(dòng)添加無參的構(gòu)造方法的!

F、在每個(gè)構(gòu)造方法中,如果使用了重載構(gòu)造函數(shù)this()方法,或者父類的構(gòu)造方法super()方法,那么this()方法或者super()方法必須放在第一行。而且這兩個(gè)方法只能選擇一個(gè),因此它們之間沒有順序問題。

G、除了編譯器生成的構(gòu)造方法,而且沒有顯式地調(diào)用super()方法,那么編譯器會(huì)插入一個(gè)super()無參調(diào)用。

H、抽象類有構(gòu)造方法。


四、靜態(tài)方法的重載與重寫(覆蓋)。

1、靜態(tài)方法是不能被覆蓋的??梢苑謨煞N情況討論:

A、子類的非靜態(tài)方法“覆蓋”父類的靜態(tài)方法。
這種情況下,是不能通過編譯的。

class Father{
static void print(){
System.out.println (
"in father method");
}
}
class Child extends Father{
void print(){
System.out.println (
"in child method");
}
}

static方法表示該方法不關(guān)聯(lián)具體的類的對(duì)象,可以通過類名直接調(diào)用,也就是編譯的前期就綁定了,不存在后期動(dòng)態(tài)綁定,也就是不能實(shí)現(xiàn)多態(tài)。子類的非靜態(tài)方法是與具體的對(duì)象綁定的,兩者有著不同的含義。

B、子類的靜態(tài)方法“覆蓋”父類靜態(tài)方法。
這個(gè)覆蓋依然是帶引號(hào)的。事實(shí)上把上面那個(gè)例子Child類的print方法前面加上static修飾符,確實(shí)能通過編譯!但是不要以為這就是多態(tài)!多態(tài)的特點(diǎn)是動(dòng)態(tài)綁定,看下面的例子:

class Father{
static void print(){
System.out.println (
"in father method");
}
}
class Child extends Father{
static void print(){
System.out.println (
"in child method");
}
}

class Test{
public static void main (String[] args) {
Father f
=new Child();
f.print();
}
}

輸出結(jié)果是:in father method
從這個(gè)結(jié)果可以看出,并沒有實(shí)現(xiàn)多態(tài)。
但是這種形式很迷惑人,貌似多態(tài),實(shí)際編程中千萬不要這樣搞,會(huì)把大家搞懵的!
它不符合覆蓋表現(xiàn)出來的特性,不應(yīng)該算是覆蓋!
總而言之,靜態(tài)方法不能被覆蓋。

2、靜態(tài)方法可以和非靜態(tài)方法一樣被重載。
這樣的例子太多了,我不想寫例程了??纯磈ava類庫中很多這樣的例子。
如java.util.Arrays類的一堆重載的binarySearch方法。
在這里提一下是因?yàn)椴橘Y料時(shí)看到這樣的話“sun的SL275課程說,靜態(tài)方法只能控制靜態(tài)變量(他們本身沒有),靜態(tài)方法不能被重載和覆蓋……”
大家不要相信??!可以重載的。而且靜態(tài)與非靜態(tài)方法可以重載。

從重載的機(jī)制很容易就理解了,重載是在編譯時(shí)刻就決定的了,非靜態(tài)方法都可以,靜態(tài)方法怎么可能不會(huì)呢?

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    亚洲欧美日本视频一区二区| 亚洲精品小视频在线观看| 在线观看免费视频你懂的| 欧美一区二区黑人在线| 一二区不卡不卡在线观看| 冬爱琴音一区二区中文字幕| 亚洲欧美日本视频一区二区| 国产精品一区日韩欧美| 午夜精品福利视频观看| 一区二区三区日韩中文| 日本一区不卡在线观看| 成年女人下边潮喷毛片免费| 98精品永久免费视频| 日本国产欧美精品视频| 午夜免费精品视频在线看| 亚洲国产精品无遮挡羞羞| 日韩一区二区三区在线日| 国产爆操白丝美女在线观看| 伊人久久五月天综合网| 亚洲综合伊人五月天中文| 国产精品成人免费精品自在线观看| 99国产高清不卡视频| 婷婷激情四射在线观看视频| 成人午夜爽爽爽免费视频| 九九热九九热九九热九九热| 久久精品国产99精品亚洲| 肥白女人日韩中文视频| 激情丁香激情五月婷婷| 欧美丰满大屁股一区二区三区| 麻豆蜜桃星空传媒在线观看| 四季精品人妻av一区二区三区| 久久精品国产99精品最新| 国产大屁股喷水在线观看视频 | 日韩中文无线码在线视频| 亚洲中文字幕视频在线播放| 欧美一区二区三区性视频 | 国产一区在线免费国产一区| 日韩美女偷拍视频久久| 欧美黄色黑人一区二区| 九九九热在线免费视频| 日韩中文字幕狠狠人妻|