Java學(xué)習(xí)之繼承、內(nèi)部類與多態(tài),包

一、繼承

當(dāng)兩個(gè)事物之間存在一定的所屬關(guān)系,即就像孩子從父母那里得到遺傳基因一樣,當(dāng)然,java要遺傳的更完美,這兩個(gè)類中,一個(gè)繼承的類(為子類或者基礎(chǔ)類)可以從被繼承的類(為父類或者超類)中獲得一些屬性和方法,而不必再自己創(chuàng)建新方法(在不需要復(fù)寫的情況等)。

1、特點(diǎn):

1、提高代碼復(fù)用性,定義在父類中的成員(變量和方法),可以被子類重復(fù)使用;

2、讓類與類之間產(chǎn)生關(guān)系,這樣就會(huì)有多態(tài)的特性。使得應(yīng)用起來(lái)更方便。

需要注意的是:
A.不可以只是為了獲取其他類的功能,簡(jiǎn)化代碼就一味的使用繼承;必須是類與類之間有所屬關(guān)系,才可以用繼承,這種關(guān)系稱為“is-a”。
B.java語(yǔ)言中,只支持單繼承,不支持多繼承。究其原因,是因?yàn)槎嗬^承容易帶來(lái)安全隱患:
a.當(dāng)多個(gè)父類中定義了相同的功能,且功能內(nèi)容不同時(shí),子類對(duì)象并不確定要運(yùn)行哪一個(gè),這就造成了程序的混亂而導(dǎo)致異常出現(xiàn)。
b但是java保留了這種機(jī)制,并改良了多繼承為多實(shí)現(xiàn),而且接口就可以多繼承。

2、使用繼承體系中的功能

1、如果使用體系,要先對(duì)體系中父類的描述進(jìn)行參閱,了解父類中的共性功能,即可以使用該體系了。這樣既可以減少查閱時(shí)間,也能更系統(tǒng)的了解體系結(jié)構(gòu),以及父類的功能。

2、具體調(diào)用父類中的功能的時(shí)候,需要?jiǎng)?chuàng)建子類對(duì)象,通過(guò)子類對(duì)象對(duì)父類方法調(diào)用,實(shí)現(xiàn)繼承。
為何要通過(guò)創(chuàng)建子類對(duì)象調(diào)用父類中的方法呢?原因如下:
a.父類很可能不可以創(chuàng)建對(duì)象,如父類是一個(gè)抽象類或者接口,這就需要子類創(chuàng)建對(duì)象,調(diào)用方法。
b.創(chuàng)建子類對(duì)象,可以使用更多的功能,如父類公有的,和子類中自定義的特有功能。

3、子父類出現(xiàn)后,類成員的特點(diǎn):

類成員:變量、函數(shù)、構(gòu)造函數(shù)
1、變量:
子父類中出現(xiàn)非私有的同名成員變量是,子類訪問(wèn)本類的同名時(shí),要用this關(guān)鍵字(如果省略了this,仍是代表本類的變量);子類訪問(wèn)父類同名變量時(shí),用super關(guān)鍵字。
補(bǔ)充:this和super兩者都存在與方法區(qū)中。
this:本類對(duì)象引用,那個(gè)對(duì)象調(diào)用this所在的函數(shù),this就代表那個(gè)對(duì)象。
super:父類對(duì)象引用,用于子類初始化父類構(gòu)造函數(shù)時(shí)等。

2、.函數(shù):(覆蓋(重寫))
當(dāng)子類同父類出現(xiàn)相同函數(shù)時(shí),子類對(duì)象調(diào)用該函數(shù)時(shí),會(huì)運(yùn)行子類內(nèi)容,如同覆蓋谷類函數(shù)一樣。實(shí)際上并沒(méi)有覆蓋父類的函數(shù),如果還需要調(diào)用父類的這個(gè)方法,需要用super.方法名即可。
舉例:

class Father  
{  
    int num = 3;  
    void show()  
    {  
        System.out.println(num);  
    }  
}  
  
class Son extends Father  
{  
    int num = 5;  
    //復(fù)寫父類函數(shù)  
    void show()  
    {  
        System.out.println(num);//this引用,此處省略this,結(jié)果是5  
        System.out.println(super.num);//super引用,結(jié)果是3.  
    }  
}  
  
class Demo  
{  
    public static void main(String [] args)  
    {  
        Son s = new Son();  
        s.show();  
    }  
}

在內(nèi)存中的加載方式:



Son中的對(duì)象加載之后,才會(huì)出現(xiàn)this和super。

應(yīng)用:
a.當(dāng)子類繼承父類時(shí),就沿襲了父類的功能,在子類中,雖然具備該功能,,但是其內(nèi)容卻與父類不同,此時(shí),可覆蓋父類的方法(即保留),使用新特性。
注意:
第一、子類權(quán)限必須大于或等于父類的才能覆蓋;
第二、靜態(tài)只能覆蓋靜態(tài)。
b.用于擴(kuò)展(新功能或內(nèi)容等)
示例如下:

class Father  
{  
    void show()  
    {  
        System.out.println("Wathing TV");  
    }  
}  
  
class Son extends Father  
{  
    //復(fù)寫父類函數(shù)  
    void show()  
    {  
        System.out.println("Wathing TV");//父類中的功能  
        System.out.println("Playing PC");//擴(kuò)展的功能  
    }  
}  
  
class Demo  
{  
    public static void main(String [] args)  
    {  
        Son s = new Son();  
        s.show();  
    }  
}

3、子父類構(gòu)造函數(shù):子類的構(gòu)造函數(shù)中有一個(gè)隱式的構(gòu)造函數(shù)
特點(diǎn):在對(duì)子類對(duì)象進(jìn)行初始化時(shí),父類構(gòu)造函數(shù)也在運(yùn)行,而且是在子類之前運(yùn)行。因?yàn)樽宇悩?gòu)造函數(shù)默認(rèn)第一行有一條隱式語(yǔ)句:super();(沒(méi)有顯式的繼承父類的類中,是默認(rèn)繼承Object的,所以構(gòu)造函數(shù)第一條語(yǔ)句仍是super();),因此會(huì)首先訪問(wèn)父類中空參數(shù)的構(gòu)造函數(shù)(在不手動(dòng)加入含有參數(shù)的super的語(yǔ)句的情況下),這是系統(tǒng)默認(rèn)的。所有的構(gòu)造函數(shù)均是如此。

需要注意的是:
a.如果父類中無(wú)空參數(shù)構(gòu)造函數(shù)(即父類中顯式的構(gòu)造了含有參數(shù)的構(gòu)造函數(shù)),必須手動(dòng)加入父類中該構(gòu)造函數(shù)。
b.構(gòu)造函數(shù)不存在覆蓋,子類中的構(gòu)造函數(shù)必定至少有一個(gè)會(huì)訪問(wèn)父類中的構(gòu)造函數(shù)。
舉例:

為什么子類一定要訪問(wèn)父類的構(gòu)造函數(shù)呢?
第一、由于父類中的數(shù)據(jù)可直接獲取,所以子類對(duì)象建立時(shí),需要先查看父類是如何對(duì)這些數(shù)據(jù)進(jìn)行初始化的。因此,子類在初始化的時(shí)候須先訪問(wèn)父類構(gòu)造函數(shù),如果父類對(duì)這些數(shù)據(jù)初始化后,可以使用,子類就無(wú)需在進(jìn)行多余的操作了。
第二、如果要訪問(wèn)指定的構(gòu)造函數(shù),可手動(dòng)定義super語(yǔ)句的方式來(lái)指定特定的構(gòu)造函數(shù)。

注意:
super語(yǔ)句一定要定義在子類構(gòu)造函數(shù)的第一條語(yǔ)句,即第一行,因?yàn)橐瘸跏蓟割悩?gòu)造函數(shù),然后再初始化子類構(gòu)造函數(shù),子類構(gòu)造函數(shù)判斷是否父類的可用,不可用則子類將其覆蓋掉,這樣子類在可以方便選擇。
構(gòu)造函數(shù)中,this和super語(yǔ)句都必須在第一語(yǔ)句出現(xiàn),因?yàn)閮烧叨际怯脕?lái)初始化的,既然是初始化,就要首先存在,就只能進(jìn)行一次,因此不能同時(shí)作為第一條語(yǔ)句出現(xiàn)。

總結(jié):子類實(shí)例化過(guò)程
1、子類所有的構(gòu)造函數(shù)默認(rèn)均訪問(wèn)父類中的空參數(shù)構(gòu)造函數(shù),因?yàn)樽宇惷總€(gè)構(gòu)造函數(shù)內(nèi)的第一行均有一句隱式的super();語(yǔ)句。
2、當(dāng)父類中悟空參數(shù)構(gòu)造函數(shù)時(shí),子類必須手動(dòng)通過(guò)super語(yǔ)句的形式指定要訪問(wèn)的父類中的構(gòu)造函數(shù)
3、子類構(gòu)造函數(shù)也可手動(dòng)指定this語(yǔ)句,來(lái)訪問(wèn)本類中的構(gòu)造函數(shù),但子類中至少要有一個(gè)構(gòu)造函數(shù)訪問(wèn)父類的構(gòu)造函數(shù)。

還有一個(gè)問(wèn)題,就是繼承是對(duì)封裝性的一個(gè)挑戰(zhàn),這個(gè)問(wèn)題是用final解決的。具體關(guān)于final在此不再贅述了。

二、內(nèi)部類

先來(lái)看一段簡(jiǎn)單的代碼:

//情況一:創(chuàng)建兩個(gè)常規(guī)類A和B  
class A{  
    int a = 5;  
    void  fun(){  
        C c = new C();  
        c.method();  
        System.out.println("A:" + a);  
    }  
  
    //情況二:將C類放入A類中  
    class C{  
        void method(){  
            System.out.println("C訪問(wèn)A:" + a);//可直接訪問(wèn)  
        }  
    }  
}  
class B{  
    void fu(){  
        int a = 6;  
        A me = new A();  
        System.out.println("訪問(wèn)A中a:" + me.a);//必須建立對(duì)象后才能訪問(wèn)  
    }  
}  
  
class  Demo  
{  
    public static void main(String[] args)   
    {  
        A x = new A();  
        B y = new B();  
        x.fun();  
        y.fu();  
    }  
}

從代碼中就可以看出,內(nèi)部類的好處。
內(nèi)部類:將一個(gè)類定義在另一個(gè)類之中。

1、訪問(wèn)規(guī)則(即使用內(nèi)部類的好處):

1、內(nèi)部類方法可以訪問(wèn)該類所在的類中作用域的成員,包括私有成員變量。
2、內(nèi)部類可以對(duì)同一個(gè)包中的其他類隱藏起來(lái),從而不被訪問(wèn)
3、使用匿名內(nèi)部類是比較便捷簡(jiǎn)單的,這種情況較多的用于AWT設(shè)計(jì)中。
注:
為何內(nèi)部類可直接訪問(wèn)外部類:
由于成員可被對(duì)象訪問(wèn),內(nèi)部類中持有了一個(gè)外部類的引用,,因此就可以直接用:外部類名.this.成員

2、訪問(wèn)格式:

1當(dāng)內(nèi)部類定義在外部類的成員位置上,而且非私有,可在外部其他類中直接建立內(nèi)部類對(duì)象
格式:外部類名.內(nèi)部類名 變量名 = 外部類對(duì)象.內(nèi)部類對(duì)象

2、當(dāng)內(nèi)部類在成員變量的位置上,可被成員修飾符修飾
·private:將內(nèi)部類在外部類中進(jìn)行封裝
·static:內(nèi)部類具備了static的特性,當(dāng)內(nèi)部類被static修飾(下面說(shuō)到的靜態(tài)內(nèi)部類),只可訪問(wèn)外部類中的static的成員,訪問(wèn)則受限。

注:(Outer為外部類名,Inner為內(nèi)部類名,function為非靜態(tài)成員)
在其他類中,如何訪問(wèn)靜態(tài)內(nèi)部類中非靜態(tài)成員:new Outer.Inner.function();(建立對(duì)象訪問(wèn))
在其他類中,如何訪問(wèn)靜態(tài)內(nèi)部類中的靜態(tài)成員:Outer.Inner.function();(可直接訪問(wèn))

注意:
1、當(dāng)內(nèi)部類中定義了靜態(tài)成員,該內(nèi)部類必須為靜態(tài)的
2、當(dāng)外部類中靜態(tài)方法訪問(wèn)內(nèi)部類時(shí),內(nèi)部類必須為靜態(tài)的
3、內(nèi)部類一般定義為private的,而很少定義為public的。

3、內(nèi)部類定義原則:------->多在程序設(shè)計(jì)中使用

1、當(dāng)描述事物時(shí),事物的內(nèi)部還有事物,則該事物使用內(nèi)部類來(lái)描述,因?yàn)閮?nèi)部事物要使用外部事物內(nèi)容
舉例來(lái)說(shuō):
樓房?jī)?nèi)部還有家庭住戶,家庭住戶中還有房間,這就可以用內(nèi)部類描述。(總不能訪問(wèn)一個(gè)住戶,就建立一個(gè)樓房對(duì)象吧,那就可真是有錢人的風(fēng)范了。)

2、何時(shí)定義內(nèi)部類:
當(dāng)一個(gè)類需要直接訪問(wèn)另一個(gè)類中的成員時(shí),則當(dāng)這個(gè)類放入另一個(gè)類中,并將內(nèi)部類封裝。

3、內(nèi)部類生成文件:
我們?cè)诰幾g一個(gè)源文件是,如果代碼中有內(nèi)部類,你會(huì)發(fā)現(xiàn),生成的class文件中含有例如這樣的文件:AC.class。這是為什么呢?因?yàn)閮?nèi)部類是一種編譯現(xiàn)象,與虛擬機(jī)無(wú)關(guān)。編譯器將會(huì)把內(nèi)部類翻譯成用(美元符號(hào))分隔外部類名和內(nèi)部類名的常規(guī)類文件,而虛擬機(jī)對(duì)此卻一無(wú)所知。

4、局部?jī)?nèi)部類(也稱局部類,方法中)

看下面一段代碼:

class A{  
    private int a = 5;  
    void  fun(){  
        class B{//在方法中創(chuàng)建一個(gè)內(nèi)部類  
            void method(){  
                System.out.println("C訪問(wèn)A:" + a);//可直接訪問(wèn)  
            }  
        }  
        B c = new B();//建立一個(gè)對(duì)象  
        c.method();  
    }  
}  
class  Demo  
{  
    public static void main(String[] args)   
    {  
        A x = new A();  
        x.fun();  
    }  
}

局部?jī)?nèi)部類:當(dāng)內(nèi)部類只在外部類中的某個(gè)方法中,創(chuàng)建了這個(gè)類型的對(duì)象時(shí),且僅使用了一次,那么可在這個(gè)方法中定義局部類。

注:
1、局部?jī)?nèi)部類不可用public或者private訪問(wèn)修飾符聲明,它的作用域被限定在了聲明這個(gè)局部類的代碼塊中
2、局部類的優(yōu)勢(shì):
a.對(duì)外界完全隱藏,即使此方法所在的類也不可訪問(wèn),也就是說(shuō),除此方法外,無(wú)任何方法知道它的存在。
b.可訪問(wèn)包含他們的外部類,因還持有外部類的引用;還可訪問(wèn)局部變量,但是局部變量必須被聲明為final。

需要注意:局部?jī)?nèi)部類不可被成員修飾符修飾,如static
代碼如下:

/* 
局部?jī)?nèi)部類測(cè)試: 
*/  
  
class Outer//類不能用private,但是內(nèi)部類是可以的  
{  
    int x = 3;  
    private static class InnerOuter//可在外部類的任意有效的地方,可以用private和static  
    {       //......  
    }  
    //含局部變量時(shí)  
    void method(final int a)//需訪問(wèn)加final  
    {  
        final int y = 4;//y需要被聲明為最終類型,即final才可被局部?jī)?nèi)部類中的成員訪問(wèn)  
        class Inner//在方法中,相當(dāng)于局部成員,不能為static或private  
        {  
            void fun()//不能定義靜態(tài)成員(變量和方法)  
            {  
                System.out.println("訪問(wèn)外部類成員變量:+ Outer.this :" + Outer.this.x);  
                System.out.println("局部?jī)?nèi)部類訪問(wèn)本地變量定義為final:" + y);  
                System.out.println("方法中的參數(shù)需定義為final:" + a);  
            }  
        }  
        new Inner().fun();  
    }  
}  
  
class InnerClassDemo0  
{  
    public static void main(String[] args)   
    {  
        Outer ou = new Outer();  
        ou.method(7);//打印3、4、7  
        ou.method(8);//打印3、4、8  
    }  
}
  • 說(shuō)明:
    method 方法中聲明了Inner的內(nèi)部類,同時(shí)也產(chǎn)生了Inner 的內(nèi)部類實(shí)例化對(duì)象,并調(diào)用其內(nèi)部的方法。
    method 方法參數(shù)a 必須定義為final,在傳入7后,運(yùn)行method方法結(jié)束后,在棧內(nèi)存中局部變量a就會(huì)隨即消亡,然后就可以再傳入8,運(yùn)行下一個(gè)method方法。

5、匿名內(nèi)部類:

1、匿名內(nèi)部類:就是內(nèi)部類的一種簡(jiǎn)寫格式。
當(dāng)只創(chuàng)建該類的一個(gè)對(duì)象,可不用再為其命名。所以稱之為匿名內(nèi)部類。

代碼示例:

class Outer2  
{  
    int x = 3;  
    public  void fun()  
    {  
        /* 
        其中Inner()被改寫為AbsDemo(){}  (其實(shí)就是對(duì)父類的復(fù)寫) 
        */  
        new AbsDemo()//看這里  
        {  
            void show()  
            {  
                System.out.println("匿名show:" + x);  
            }  
        }.show();  
    }  
}

2、定義前提:
內(nèi)部類必須繼承一個(gè)類或?qū)崿F(xiàn)接口。

但是有一種很特殊,可以不直接繼承一個(gè)父類,仍可定義一個(gè)匿名內(nèi)部類。因?yàn)槿魏晤惗际荗bject的子類。
如:

new Object()  
{  
         類中的內(nèi)容  
         fun()方法  
}.fun();  

3、格式:

new    父類或接口(參數(shù)){定義子類的內(nèi)容};

4、要點(diǎn)說(shuō)明:
A.其實(shí)匿名內(nèi)部類就是一個(gè)匿名子類對(duì)象,可以理解為帶有內(nèi)容的對(duì)象。
B.匿名內(nèi)部類中的方法最好少于3個(gè),方法少,比較方便簡(jiǎn)單,匿名內(nèi)部類一定要簡(jiǎn)化,否則就違背了初衷。

6、靜態(tài)內(nèi)部類

1、概述:
上面提到當(dāng)內(nèi)部類在成員變量的位置上,可被成員修飾符static修飾,這就是靜態(tài)內(nèi)部類

2、使用前提:
某些情況下,會(huì)把內(nèi)部類作為一個(gè)隱藏的類,不需要使用內(nèi)部類引用外部類的對(duì)象。因此,可以將外部類聲明為static,就可以消除產(chǎn)生的引用。在內(nèi)部類不需要訪問(wèn)外部類對(duì)象的時(shí)候,應(yīng)該使用靜態(tài)內(nèi)部類。

下面是示例:

/* 
靜態(tài)內(nèi)部類測(cè)試:最大值最小值 
*/  
  
class ArrayAlg  
{  
    public static class Pair  
    {  
        private double first;  
        private double second;  
        //構(gòu)造函數(shù)獲得兩個(gè)值  
        public Pair(double first,double second)  
        {  
            this.first = first;  
            this.second = second;  
        }  
          
        //訪問(wèn)器:訪問(wèn)私有變量first和second  
        public double getFirst()  
        {  
            return first;  
        }  
        public double getSecond()  
        {  
            return second;  
        }  
    }  
    //定義一個(gè)獲得最大值和最小值的功能  
    public static Pair minmax(double[] arr)  
    {  
        //min和max要分別設(shè)置最大和最小,然后才能和數(shù)組中的數(shù)比較  
        double min = Double.MAX_VALUE;  
        double max = Double.MIN_VALUE;  
  
        for (int i=0;i<arr.length;i++)  
        {  
            if (min > arr[i])  
                min = arr[i];  
            if (max < arr[i])  
                max = arr[i];  
        }  
        return new Pair(min,max);  
    }  
}  
  
class ArrayZDemo  
{  
    public static void main(String[] args)   
    {  
        double[] d = new double[20];  
        for (int i=0;i<d.length;i++)  
            d[i] = 100*Math.random();  
        ArrayAlg.Pair p = ArrayAlg.minmax(d);  
        System.out.println("min = " + p.getFirst());  
        System.out.println("max = " + p.getSecond());  
    }  
}

練習(xí):

interface Inter  
{  
    void method();  
}  
class Test  
{  
    //補(bǔ)足代碼,用匿名內(nèi)部類  
}  
class NInnerClassTest  
{  
    public static void main(String[] args)   
    {  
        Test.function().method();  
    }  
}

對(duì)于Test.function().method();的理解:
Test.function():類中有一個(gè)靜態(tài)的方法function。
method():function這個(gè)方法運(yùn)算后的結(jié)果是一個(gè)對(duì)象,而且是一個(gè)Inter類型的對(duì)象。
--->因?yàn)橹挥惺荌nter類型的對(duì)象,才可以調(diào)用method方法。
結(jié)果:

interface Inter  
{  
    void method();  
}  
  
class Test  
{  
    public static Inter function()  
    {  
        return new Inter()  
        {  
            public void method()  
            {  
                System.out.println("使用靜態(tài)");  
            }  
        };  
    }  
}  
//測(cè)試結(jié)果  
class NInnerClassTest  
{  
    public static void main(String[] args)   
    {  
        Test.function().method();  
    }  
}

匿名內(nèi)部類的應(yīng)用:

class NInnerClassTest  
{  
    public static void main(String[] args)   
    {  
        show(new Inter()  
        {  
            public void method()  
            {  
                System.out.println("method show run");  
            }  
     
  
    }  
    public static void show(Inter a)  
    {  
        a.method();  
    }  
}

三、多態(tài)

多態(tài):可理解為事物存在的多種體現(xiàn)形態(tài)。又稱為動(dòng)態(tài)綁定,是java的核心機(jī)制之一。

理解:多態(tài)是在運(yùn)行期間,判斷引用實(shí)際類型,根據(jù)實(shí)際類型調(diào)用相應(yīng)的方法。
比如說(shuō)人又男女之分,動(dòng)物有貓、狗等之分

1、多態(tài)的體現(xiàn)形式:

1、父類的引用指向了自己子類的對(duì)象。

2、父類的引用可接收子類的對(duì)象。

比如說(shuō)Person p = new Student();中p指向了Student中的一個(gè)對(duì)象。
如圖:

Paste_Image.png

2、多態(tài)的前提:

1、必須是類與類之間的關(guān)系,如繼承和實(shí)現(xiàn)關(guān)系

2、要存在覆蓋的操作,父類中必須由方法被子類覆蓋,即重寫

3、有父類引用指向子類對(duì)象

3、多態(tài)的利弊:

1、好處:大大提高了程序的擴(kuò)展性

2、弊端:雖然提高擴(kuò)展性,但是只能使用父類的引用訪問(wèn)父類中的成員,不可預(yù)先使用子類。這是由于,子類在父類之后加載,此時(shí)還沒(méi)有子類被加載。

在下面的代碼中,Animal a = new Cat();是一種“類型提升,向上轉(zhuǎn)型”的過(guò)程。如果要實(shí)現(xiàn)Cat中的其他Animal沒(méi)有的功能,那么就需要強(qiáng)制將父類的引用轉(zhuǎn)換成子類類型,然后再調(diào)用子類的方法:

Cat c = (Cat) a;
c.catchM();

注意:
1、一定不能將父類的對(duì)象轉(zhuǎn)換成子類類型。
2、可轉(zhuǎn)換的:父類引用指向自己子類的對(duì)象時(shí),該引用可被提升,也可被強(qiáng)制轉(zhuǎn)化。
3、多態(tài)自始至終均為子類對(duì)象在做變化。

例如:

/** 
分析: 
    1、定義一個(gè)動(dòng)物類這個(gè)超類類型(抽象),含有一個(gè)吃飯的抽象方法 
    2、定義子類(如貓,狗等),含有自己的方法(貓:抓老鼠;狗:看家) 
    3、用多態(tài)實(shí)現(xiàn)子類方法 
*/  
abstract class Animal   //抽象類  
{  
    abstract void eat();  
}  
  
class Cat extends Animal  //Cat繼承父類Animal  
{     
    //復(fù)寫父類的抽象方法  
    void eat(){  
  
        System.out.println("吃魚(yú)");  
    }  
  
    //定義自身功能  
    void catchM(){  
  
        System.out.println("抓老鼠");  
    }  
}  
  
class Dog extends Animal  
{  
      
    //復(fù)寫父類的抽象方法  
    void eat(){  
        System.out.println("啃骨頭");  
    }  
    //定義自身功能  
    void kanJ(){  
        System.out.println("看家");  
    }  
}  
class DuoTaiTest  
{  
    public static void main(String[] args)  
    {  
        Animal a1 = new Cat();//多態(tài)運(yùn)用a2.eat();  
        Dosome(a1);  
        Cat c = (Cat)a1;  
        Dosome(c);  
        c.catchM();  
        Animal a2 = new Dog();  
        a2.eat();  
        Dosome(a2);  
        Dog d = (Dog)a2;  
        Dosome(d);  
        d.kanJ();  
    }  
    public static void Dosome(Animal a)  
    {  
        a.eat();  
    }  
}

4、多態(tài)的特點(diǎn):

1、在多態(tài)中成員函數(shù)的特點(diǎn):

·編譯時(shí)期:參閱引用型變量所屬的類中,是否有調(diào)用的方法,如果有,則編譯通過(guò),若沒(méi)有,則編譯失敗。如上面的代碼中,引用型變量a是父類Animal的類型,其中有eat 的方法,所以沒(méi)問(wèn)題,但是如果調(diào)用a.catchM()就會(huì)編譯失敗。

·運(yùn)行時(shí)期:參與對(duì)象所屬的類中,是否有調(diào)用的方法。如引用型變量c是所屬于Cat類型的,可以調(diào)用c.catchM()

總結(jié):成員函數(shù)在多態(tài)調(diào)用時(shí),編譯看左邊,運(yùn)行看右邊。子類中局部有變量就訪問(wèn)局部的,沒(méi)有就訪問(wèn)成員的變量,成員中沒(méi)有的就在父類中找;如果父類中沒(méi)有,編譯失敗。

2、在多態(tài)中成員變量(和靜態(tài)成員)的特點(diǎn):
·無(wú)論編譯和運(yùn)行,都參考左邊的,即引用型變量所屬的類型。也就是說(shuō)父類中有自己的變量,則先找父類自己的成員。

·非靜態(tài)有重寫的特點(diǎn),靜態(tài)一般不被重寫。

原因:因?yàn)楫?dāng)調(diào)用靜態(tài)方法時(shí),只要建立子類對(duì)象,父類與子類中的靜態(tài)方法都會(huì)隨之加載入內(nèi)存,是不需要調(diào)用就可直接用類名.方法名的,而不需要對(duì)象。只要引用還存在,就看引用變量的類型。

class Father  
{  
    int num = 3;  
    void method1()  
    {  
        System.out.println("father-1");  
    }  
      
    void method2()  
    {  
        System.out.println("father-2");  
    }  
      
    static void method4()  
    {  
        System.out.println("father-4");  
    }  
}  
  
class Son extends Father  
{  
    int num = 5;  
    void method1()  
    {  
        System.out.println("son-1");  
    }  
      
    void method3()  
    {  
        System.out.println("son-3");  
    }  
      
    static void method4()  
    {  
        System.out.println("son-4");  
    }  
}  
class DuotaiYYDemo  
{  
    public static void main(String[] args)   
    {  
        Father f = new Son();  
        Son s = new Son();  
        f.method1();//son-1  
        s.method1();//son-1  
        f.method2();//father-2  
        s.method3();//son-3  
        //f.method3();報(bào)錯(cuò)  
        f.method4();//father-4  
        s.method4();//son-4  
        System.out.println(f.num);//3  
        System.out.println(s.num);//5  
    }  
}

注:
如果在每次調(diào)用方法時(shí)都要進(jìn)行搜索的話,效率是非常低的。因此,JVM虛擬機(jī)會(huì)預(yù)先為每個(gè)類在方法區(qū)創(chuàng)建一個(gè)方法表,列出了所有方法的參數(shù)和實(shí)際調(diào)用的方法。因此,在真正調(diào)用的時(shí)候,虛擬機(jī)只查找這個(gè)方法表就可行了。而且,方法區(qū)中會(huì)有靜態(tài)方法區(qū)和非靜態(tài)方法區(qū)之分(如圖)。其中像this和super這兩個(gè)關(guān)鍵字存在于非靜態(tài)方法區(qū)中,而被static修飾的,存在于靜態(tài)方法區(qū)中。

5、多態(tài)的應(yīng)用

1、定義好工具類,即將共同行為封裝在一個(gè)類中。
2、對(duì)類型進(jìn)行抽取,---->多態(tài)的產(chǎn)生。
3、操作同一個(gè)大類型,對(duì)其中的小類型均可操作

四、包

1、包概述:

java中的包就相當(dāng)于系統(tǒng)中的文件夾。
當(dāng)我們需要將各個(gè)類分門別類的存放的時(shí)候,或者含有不同功能的相同類名的時(shí)候,需要用到包(package)。包可以將相關(guān)的類放在一起,并可以將兩個(gè)或多個(gè)相同文件名的文件放在不同包中。

2、包的作用:

1、為避免多個(gè)類重名的情況,如果出現(xiàn)兩個(gè)相同名字的類,可通過(guò)包將兩者區(qū)分,從而避免沖突
2、對(duì)類文件進(jìn)行分類管理,可以將相關(guān)的一些類放在同一個(gè)包中。
3、給類提供多層命名空間,如a包中的Demo.class文件即packagea.Demo.class

3、規(guī)則:

1、寫在程序的第一行,因?yàn)槭前碌念悾扔邪耍拍軐㈩惙胚M(jìn)去。
2、類名的全稱:包名.類名
3、包是一種封裝形式,是java封裝性的體現(xiàn)。

4、包與包之間的訪問(wèn):

1、要訪問(wèn)其他包中的類,需要定義類名的全名:包名.類名
2、如果包不再當(dāng)前目錄下,需要設(shè)置classpath,告知虛擬機(jī)包的執(zhí)行路徑
3、有了包,范圍變大,一個(gè)包中的類要被訪問(wèn),必須有足夠大的權(quán)限。

注:
a.包與包間進(jìn)行訪問(wèn),被訪問(wèn)的包中的類以及類中的成員,需要public修飾。
b.不同包中的子類還可直接訪問(wèn)父類中被protected權(quán)限修飾的成員。包與包間可使用的權(quán)限有兩種:public和protected。
c.其中protected只用于覆蓋。

示例:

package cn.conpany.test;  
  
public class FatherDemo {  
    //父類受保護(hù)方法  
    protected void show(){  
        System.out.println("protected father");  
    }  
    //父類公有方法  
    public void fuc(){  
        System.out.println("public father");  
    }  
}
package cn.conpany.test.array;  
  
public class SonDemo extends cn.conpany.test.FatherDemo{  
    public void showSon(){  
        //自定義方法  
        System.out.println("son show");  
        //調(diào)用父類方法  
        show();  
    }  
}
package cn.conpany.test.object;  
  
import cn.conpany.test.FatherDemo;  
import cn.conpany.test.array.SonDemo;  
  
public class PackageDemo {  
  
    public static void main(String[] args) {  
        //創(chuàng)建子父類對(duì)象  
        FatherDemo f = new FatherDemo();  
        SonDemo s = new SonDemo();  
        //類PackageDemo可訪問(wèn)其他類公有方法  
        f.fuc();//public father  
        //訪問(wèn)其他類受保護(hù)方法,不可  
        //f.show();//報(bào)錯(cuò)  
        s.fuc();//public father  
        //子類可訪問(wèn)父類受保護(hù)方法  
        s.showSon();/*son show 
                    protected father*/  
    }  
}

5、包的導(dǎo)入:

1、為了簡(jiǎn)化類名的書(shū)寫,使用import導(dǎo)入
如:import packa.packb.packc.*; 是將包packa下的包packb下的包packc下的所有類導(dǎo)入進(jìn)來(lái)。
注:如果需要packb下還有類需要導(dǎo)入,則還需在導(dǎo)入,
如: import packa.packb.*;

2、注意事項(xiàng):
a.兩個(gè)包中有相同類名文件,當(dāng)再統(tǒng)一類中創(chuàng)建對(duì)象時(shí),需要加上包名.類名創(chuàng)建。
b.建議定義包名不要重復(fù),可以使用URL來(lái)定義,因?yàn)閁RL是唯一的。
如:
www.itcast.com---->package cn.itcast.Demo以及cn.itcast.Test

Java中各個(gè)主要包的作用(javax開(kāi)頭的都是擴(kuò)展包)
java.util是JAVA的utility工具包,包含一些使用工具類,如定義系統(tǒng)特性、使用與日期日歷相關(guān)的函數(shù)等的類
java.lang是JAVA的language核心語(yǔ)言包;如String、Math、Integer、System、Thread,提供常用的功能。特殊之處是不需要導(dǎo)入,是作為默認(rèn)導(dǎo)入的包。
java.awt是JAVA的abstractwindow toolkit,抽象窗口工具包;包含了構(gòu)成抽象窗口共具體的多個(gè)類,這些類用于構(gòu)建和管理應(yīng)用程序的圖形用戶(GUI)。
java.applet是創(chuàng)建APPLET的必須包;包含applet運(yùn)行時(shí)所需要的一些類。
java.net是JAVA有關(guān)網(wǎng)絡(luò)操作的包。
java.io是JAVA的輸入輸出流的包。
java.sql是JAVA的數(shù)據(jù)庫(kù)操作包。
javax.swing是新的界面包。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,870評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,742評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,527評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,010評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,250評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,656評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,853評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,103評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,472評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,717評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,487評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,815評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容

  • 一:java概述:1,JDK:Java Development Kit,java的開(kāi)發(fā)和運(yùn)行環(huán)境,java的開(kāi)發(fā)工...
    ZaneInTheSun閱讀 2,674評(píng)論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,710評(píng)論 18 399
  • 一、多態(tài) 1. 概述 理解:多態(tài)可以理解為事物存在的多種體(表)現(xiàn)形態(tài)。例如:動(dòng)物中的貓和狗。貓這個(gè)對(duì)象對(duì)應(yīng)的是貓...
    陳凱冰閱讀 341評(píng)論 0 1
  • Unsupported major.minor version 51.0解決辦法 具體步驟 解決:項(xiàng)目------...
    晨星資源閱讀 603評(píng)論 0 1
  • 1.import static是Java 5增加的功能,就是將Import類中的靜態(tài)方法,可以作為本類的靜態(tài)方法來(lái)...
    XLsn0w閱讀 1,252評(píng)論 0 2