Java學習日記基礎(五)——類、對象之this、靜態變量(類變量)、靜態方法(類方法)、四大特征


this

趙本山問奧尼爾:“我的爸爸的爸爸是誰?”

奧尼爾:“不知道”

趙本山:“你傻啊,是我爺爺”

奧尼爾回去問科比:“我的爸爸的爸爸是誰?”

科比:“不知道”

奧尼爾:”你傻啊,是趙本山的爺爺“

就像這個笑話一樣,不同的人,用this時,指向的對象也是變的。

 普通方法中,this總是指向調用該方法的對象

//this在成員方法中的用處
//this就是指代當前對象,是一個隱式參數

public class thissss
{
	public static void main(String []args)
	{
		Student s1 = new Student();
		s1.name = "小白";
		s1.age = 17;
		s1.study();
		System.out.println(s1.name);
		Student s2 = new Student();
		s2.name = "小徐";
		s2.age = 18;
		s2.study();
	}
}


class Student
{
	int age;
	String name;
	public void study()		
	//在創建成員方法(函數)的時候會自動傳一個this參數,指向該對象的地址,但是是隱藏的
	{
		this.name = "小黑";
		//s1.name = "小黑";
		//這條語句是錯誤的,因為對象要在類創建完成之后才有
		//但是使用this.name就可以給類進行賦值
		//因為this指向創建的對象的地址,所以this.name就會找到該對象中study()方法的地址
		//對這個地址進行操縱,總而更改當前對象的值
		System.out.println(name+"在學習");
	}
}

圖解:

構造方法中,this總是指向正要初始化的對象

//this在構造方法中的用處
//用來指向正在初始化的對象
public class thissss2
{
	public static void main(String []args)
	{
		Student s1 = new Student(17);
		System.out.println(s1.age);
		Student s2 = new Student(18);

	}
}


class Student
{
	int age;
	String name;
	public Student(int age)
	{
		//age = age
		//直接寫age指代的是public void Student(String name,int age)傳進來的name,就近原則
		//this.age指代的是當前正在初始化的對象中的String age;
		this.age = age;
	}	
}

輸出結果:
age = age時,輸出的是0,並非是正常的結果
this.age = age時,輸出的是正常的結果17

  原因也是因為會默認傳一個this參數,用來指向當前使用這條命令的對象的地址,這樣就可以正確的初始化當前對象中成員變量的值了

  注意:this不能用於static方法(學了static方法就知道為什么了)

變量的種類

實例變量、類變量、常量都是屬於成員變量的,成員變量又被稱為全局變量

 

public class A{
    String id;                          //實例變量
    private String Tel;              //實例變量
    private int size;                 //實例變量
    private static String depart;             //類變量
    final String design="樣式";                //常量
}
 
/*其中實例變量、類變量、常量都是屬於成員變量的,成員變量又被稱為全局變量,
成員變量的范圍比實例變量更寬泛 */               

 

方法(函數)的種類

實例方法(instance method):或叫成員方法(member method)。供實例用的方法,必須要先有實例,才能通過此實例調用實例方法。

靜態變量 / 類變量

提問:有一群小孩在玩堆雪人,不時有新的小孩加入,請問如何知道現在有多少人在玩呢?請使用面向對象的思想,編程解決。

 1 public class Demo1
 2 {
 3     public static void main(String []args)
 4     {
 5         int total = 0;
 6         Child ch1 = new child(3,"小徐");
 7         ch1.joinGame();
 8         total++;
 9         
10         Child ch2 = new child(4,"小白");
11         ch2.joinGame();
12         total++;
13         //查看總人數的時候,只需要輸入total的值就可以了
14         //但是要求是使用面向對象的方法,課時這個total並沒有封裝到對象中去
15     }
16 }
17 
18 //定義kid類
19 class Child
20 {
21     int age;
22     String name;
23     public Child(int age,String name)
24     {
25         this.age = age;
26         this.name = name;
27     }
28     public void joinGame()
29     {
30         System.out.println("有一個小孩加入了");
31     }
32 }
一般人的思維

從上面的例子中可以看到,要是有一個所有對象都能操作的變量就好了,而java中確實有這個變量,叫做靜態變量(也叫類變量)

public class Demo1
{
    public static void main(String []args)
    {
        Child ch1 = new Child(3,"小徐");
        ch1.joinGame();
        Child ch2 = new Child(4,"小白");
        ch2.joinGame();
        System.out.println("公有="+ch2.total);
        //也可以直接用類訪問靜態變量
        System.out.println("公有="+Child.total);
        
    }
}

//定義kid類
class Child
{
    int age;
    String name;
    //total是靜態變量, 因此可以被任何一個對象訪問
    static int total = 0;
    public Child(int age,String name)
    {
        this.age = age;
        this.name = name;
    }
    public void joinGame()
    {
        total++;        //在這里進行計數操作
        System.out.println("有一個小孩加入了");
    }
}
靜態變量實現

什么是:靜態變量(類變量)?

  類變量是該類的所有對象的共享變量,任何一個該類的對象去訪問它是,取到的都是相同的值,同樣任何一個該類的對象去修改它時,修改的也是同一個變量。

靜態變量的定義語法

訪問修飾符   static  數據類型  變量名;

靜態變量的訪問方法

  • 類名 . 靜態變量名
  • 對象名 . 靜態變量名  

加深靜態方法的理解的小例子

 1 public class Demo2
 2 {
 3     static int i=1;
 4     static         //靜態區域塊只會被執行一次
 5     {
 6         i++;
 7     }
 8     public Demo2()
 9     {
10         i++;
11     }
12     
13     public static void main(String []args)
14     {
15         Demo2 t1 = new Demo2();
16         System.out.println(t1.i);
17         Demo2 t2 = new Demo2();
18         System.out.println(t2.i);
19         
20     }
21 }
猜猜看吧

原理:

 1 public class Demo2
 2 {
 3     static int i=1;
 4     static         //靜態區域塊只會被執行一次
 5     {
 6         i++;
 7         System.out.println("靜態區域塊");
 8     }
 9     public Demo2()
10     {
11         i++;
12         System.out.println("成員方法Demo2");
13     }
14     
15     public static void main(String []args)
16     {
17         Demo2 t1 = new Demo2();
18         System.out.println(t1.i);
19         Demo2 t2 = new Demo2();
20         System.out.println(t2.i);
21         
22     }
23 }
24 
25 輸出結果:
26 靜態區域塊
27 成員方法Demo2
28 3
29 成員方法Demo2
30 4
運行結果和原理

不創建對象static也會執行,原理將來會講

public class Demo2
{
    static int i=1;
    static         //靜態區域塊只會被執行一次
    {
        i++;
        System.out.println("靜態區域塊");
    }
    public Demo2()
    {
        i++;
        System.out.println("成員方法Demo2");
    }
    
    public static void main(String []args)
    {
    }
}

輸出結果:
D:\myJavaDemo\Day3>java Demo2
靜態區域塊
static

靜態方法(類方法)

小例子:

public class Demo3
{
	public static void main(String []args)
	{
		//創建一個學生
		Stu stu1=new Stu(29,"aa",340);
		Stu stu2 = new Stu(29,"aa",290);
		System.out.println(stu2.getTotalFee());
		//此時這個語法是有歧義的,感覺輸出的是stu2的學費,但是輸出的是所有學生的費用		
	}
}

class Stu
{
	int age;
	String name;
	int fee;
	static int totalFee;
	
	public Stu(int age,String name,int fee)
	{
		this.age = age;
		this.name = name;
		totalFee+=fee;
	}
	public int getTotalFee()
	{
		return totalFee;
	}
}

使用靜態方法

java中有一個規則,靜態變量原則用靜態方法去訪問和操作,約定俗成的。並且

  • 靜態方法中不能對非靜態變量操作
  • 但普通的成員方法可以操作靜態變量,
  • 靜態變量都可以被操作,非靜態方法不能被靜態方法操作
 1 public class Demo3
 2 {
 3     public static void main(String []args)
 4     {
 5         //創建一個學生
 6         Stu stu1=new Stu(29,"aa",340);
 7         Stu stu2 = new Stu(29,"aa",290);
 8         //可以直接使用Stu類名來訪問這個靜態方法
 9         System.out.println(Stu.getTotalFee());
10         
11     }
12 }
13 
14 class Stu
15 {
16     int age;
17     String name;
18     int fee;
19     static int totalFee;
20     
21     public Stu(int age,String name,int fee)
22     {
23         this.age = age;
24         this.name = name;
25         totalFee+=fee;
26     }
27     public static int getTotalFee()  //區別就是這條語句中多了一個static
28     {
29         return totalFee;
30     }
31 }
靜態方法(函數)

什么時候使用靜態方法?

如果有一個方法(函數)需要讓所有的對象去共享的時候,就可以設計成為靜態方法

靜態方法的語法

訪問修飾符  static  數據返回類型  方法名 ()
{
            //語句;
}


//注意靜態方法中不能訪問非靜態變量,例如: 成員屬性

使用方法

類名 . 靜態方法名
對象名 . 靜態方法名

類變量與實例變量的區別

靜態變量(類變量)
int a;
String name;

實例變量
int static a;
String static name;
  • 加上static稱為靜態變量或類變量 ,否則稱為實例變量
  • 類變量是與類相關的,公共的屬性
  • 實例變量是屬於每個對象個體的屬性
  • 類變量可以通過 類名.類變量名 直接訪問  

靜態方法(類方法)與實例方法的區別

靜態方法(類方法)
public static int getTotalFee()  
	{
		return totalFee;
	}

實例方法
public int getTotalFee()
	{
		return totalFee;
	}
  • 類方法屬於與類相關的,公共的方法  
  •  實例方法屬於每個對象個體的方法
  • 類方法可以通過  類名.類方法名  直接訪問

四大特征——抽象、封裝、繼承、多態

一般是說java有三大特征,即封裝、繼承、多態。但有人也會把抽象算進去,如順平

抽象

   我們前面在定義一個類的時候,實際上就是把一類事物共有的屬性和行為提取出來,形成一個物理模型(模板)。這種研究問題的方法稱為抽象。

封裝

封裝就是把抽象出的數據和對數據的操作封裝在一起,數據被保護在內部,程序的其它部分只有通過被授權的操作(成員方法),才能對數據進行操作。

就像電視機一樣,電路板被保護在內部,我們不能直接操作電路板,但是我們可以通過電視機上的按鈕來的操作電路板,從而達到我們的目的。

訪問控制修飾符

小例子:訪問公有的成員變量

 1 public class Demo4
 2 {
 3     public static void main(String []args)
 4     {
 5         Clerk clerk1 = new Clerk("小花",24,4567.6f);
 6         System.out.println("名字是"+clerk1.name);
 7         
 8     }
 9 }
10 
11 class Clerk
12 {
13     public String name;        //public共有的
14     private int age;        //private私有的
15     private float salary;
16     
17     public Clerk(String name,int age,float sal)
18     {
19         this.name = name;
20         this.age = age;
21         this.salary = sal;
22     }
23 }
24 
25 輸出結果:
26 名字是小花
公有

但訪問私有的成員變量時,會報錯

 1 public class Demo4
 2 {
 3     public static void main(String []args)
 4     {
 5         Clerk clerk1 = new Clerk("小花",24,4567.6f);
 6         System.out.println("名字是"+clerk1.name);
 7         
 8     }
 9 }
10 
11 class Clerk
12 {
13     public String name;        //public共有的
14     private int age;        //private私有的
15     private float salary;
16     
17     public Clerk(String name,int age,float sal)
18     {
19         this.name = name;
20         this.age = age;
21         this.salary = sal;
22     }
23 }
24 
25 報錯信息:
26 Demo4.java:11: 錯誤: salary 在 Clerk 中是 private 訪問控制
27                 System.out.println("薪水是"+clerk1.salary);
28                                                ^
29 1 個錯誤
私有

通過成員方法去控制和訪問私有的屬性

 1 public class Demo4
 2 {
 3     public static void main(String []args)
 4     {
 5         Clerk clerk1 = new Clerk("小花",24,4567.6f);
 6         System.out.println("薪水是"+clerk1.getSal());
 7         
 8     }
 9 }
10 
11 class Clerk
12 {
13     public String name;        //public共有的
14     private int age;        //private私有的
15     private float salary;
16     
17     public Clerk(String name,int age,float sal)
18     {
19         this.name = name;
20         this.age = age;
21         this.salary = sal;
22     }
23     //通過一個成員方法去控制和訪問私有的屬性
24     public float getSal()
25     {
26         return this.salary;
27     }
28 }
29 
30 輸出結果:
31 薪水是4567.6
通過公開的成員方法訪問私有的屬性

因為成員方法是公開的(public),可以被使用。

就像我們使用電視機的時候不能通過操作電路板來換台、調節音量,但是我們可以通過操作電視機給我們提供的按鈕來進行換台、調節音量的操作。電視機上的按鈕就相當於成員方法。

  • 廠商不讓我們操作電路板,但是讓我們操作按鈕來間接操作電路板。
  • 類不讓我們訪問私有的屬性,但是讓我們使用成員方法來訪問私有屬性。

Java提供四種訪問控制修飾符號 控制 方法和變量 的訪問權限

  • 公開級別:用 pulic 修飾,對外公開
  • 受保護級別:用 protected 修飾,對子類和同一個包中的類公開
  • 默認級別:沒有修飾符號,像同一個包的類公開
  • 私有級別:用 private 修飾,只有類本身可以訪問,不對外空開

從包開始,就不用記事本寫程序了,改成用eclipse了

包的必要性?

 有這樣的一種情況,小白定義了一個類取名為Dog,賽拉也定義了一個類取名為Dog,然后他們倆就打起來了。我們使用myeclipse來模擬一下這種情況

   

小徐此時站了起來,說:“你們是傻嗎?不知道包的作用!”

.代表再分一層

包的作用

  1. 區分相同名字的類
  2. 當類很多時,可以很好的管理
  3. 控制訪問范圍

打包命令

命令一般放在文件開頭的地方

package com.shunping;    //這條命令會自動生成,會自動把字節碼放到com.shunping這個包中去

命名規范

//包名都是小寫字母 , 用 . 隔開 , 比如
com.sina.shunping  

常用的包

一個包下,包含很多的類,java中常用的包有:

  • java.lang.* —— 這個包是自動引入的
  • java.util.* —— 工具包
  • java.net.* —— 網絡開發包
  • java.awt.* —— 窗口工具包

引入一個包

語法 :  import   包;
import  java.awt.* ;

  我們引入一個包的主要目的是使用該包下的類

 用包來控制訪問范圍

 1 package com.xiaoqiang;
 2 
 3 public class Test 
 4 {
 5     public static void main(String[] args) 
 6     {
 7         Dog dog1 = new Dog();
 8 
 9                 //驗證同包下的權限訪問情況
10         System.out.println(dog1.a);
11 
12     }
13 
14 }
15 class Dog
16 {
17     public int a;
18     protected String name;
19     String color;
20     private float price;
21     
22         //驗證同類下的權限訪問情況
23     public void ab1()
24     {
25         System.out.println(this.a);
26         
27     }
28 }        
在小強的Dog類中創建四種類型的訪問控制修飾符

 同類下的訪問權限

同包下的訪問權限——沒有私有屬性的price類

不同包下的訪問權限用——用小明去訪問小強中的Dog類

在小強的包下新建一個公有的Cat類,里面的內容和Dog相同,此時小明的訪問情況為

 1 package com.xiaoqiang;
 2 
 3 public class Cat 
 4 {
 5     public int a;
 6     protected String name;
 7     String color;
 8     private float price;
 9     
10     public void ab1()
11     {
12         System.out.println(this.a);
13         
14     }    
15 }
小強下的公有Cat類

權限訪問情況為——只能訪問公有類

如果我就是想訪問其它的屬性呢?

——這時就要用到封裝的思想,用公有的成員方法去訪問私有屬性

 1 package com.xiaoqiang;
 2 
 3 public class Cat 
 4 {
 5     public int a;
 6     protected String name;
 7     String color;
 8     private float price;
 9     
10     //提供一個訪問name的成員方法
11     public String getName()
12     {
13         return this.name;
14         
15     }
16     
17     
18 }
在Cat類中提供一個訪問name屬性的成員方法

繼承

 為什么有繼承?

小例子:我們定義小學生,中學生,大學生類

 1 public class Demo 
 2 {
 3     public static void main(String[] args) 
 4     {
 5     }
 6 
 7 }
 8 
 9 //小學生類
10 class Pupil
11 {
12     //定義成員屬性
13     private int age;
14     private String name;
15     private float fee;
16     
17     //交費
18     public void pay(float fee)
19     {
20         this.fee = fee;
21     }
22 }
23 
24 //中學生類
25 class MiddleStu
26 {
27     //定義成員屬性
28     private int age;
29     private String name;
30     private float fee;
31     
32     //交費
33     public void pay(float fee)
34     {
35         this.fee = fee*0.8f;
36     }
37 }
38 
39 //大學生類
40 class ColStu
41 {
42     //定義成員屬性
43     private int age;
44     private String name;
45     private float fee;
46     
47     //交費
48     public void pay(float fee)
49     {
50         this.fee = fee*0.1f;
51     }
52 }
類中成員屬性重復現象

繼承就可以很好的解決代碼重復問題,讓我們的編程更加靠近人類的思維。

當多個類中存在相同的屬性(變量)和方法時,可以從這些類中抽象出父類,在父類中定義這些相同的屬性和方法。這樣所有的子類不需要重新定義這些屬性和方法,只需要通過extends語句來把父類的這些屬性和方法繼承過來就行。

 1 public class Demo 
 2 {
 3     public static void main(String[] args) 
 4     {
 5     }
 6 
 7 }
 8 //將學生的共有屬性抽象出來, 做一個父類
 9 class Student
10 {
11     public int age;
12     public String name;
13     public float fee;
14     
15 }
16 //小學生類
17 class Pupil extends Student{
18     //交費
19     public void pay(float fee)
20     {
21         this.fee = fee;
22     }
23 }
24 //中學生類
25 class MiddleStu extends Student{    
26     //交費
27     public void pay(float fee)
28     {
29         this.fee = fee*0.8f;
30     }
31 }
32 //大學生類
33 class ColStu extends Student{
34     //交費
35     public void pay(float fee)
36     {
37         this.fee = fee*0.1f;
38     }
39 }
簡單的繼承例子

繼承的語法

class  子類  extends  父類 ;
//這樣子類就會自動擁有父類定義的某些屬性和方法,有些東西是繼承不了的

深入探討——父類的哪些屬性(變量)、方法被子類繼承了

父類: 
{
	public int a;
	protected int b;
	int c;
	private int d;

	public int getA(){}
	protected int getB(){}
	int getC(){}
	private int getD(){}	
}
    ————————————繼承————————————
子類: 
{
	public int a;
	protected int b;
	int c;

	public int getA(){}
	protected int getB(){}
	int getC(){}
}

  可以看出只有private修飾符的屬性和方法不能被子類繼承,所以不希望子類繼承的屬性和方法,只需要把那個屬性和方法設置為private屬性即可

繼承的注意事項

  1. 子類最多只能繼承一個父類(指直接繼承),可以通過接口進行多重繼承 ,之后會講
  2. java所有類都是Object類的子類
  3. JDK6中有202個包,3777個類、接口、異常、枚舉、注釋和錯誤,掌握150個就是大神了
  4. 在做開發的時候,強烈建議大家多查jdk幫助文檔,還是不會就google
import javax.swing.*;
public class Demo2 extends JFrame {

    public static void main(String[] args) {
        Demo2 demo2 = new Demo2();
        

    }
    public Demo2()
    {
        this.setVisible(true);
        this.setSize(200 , 200);
    }

}
案例:利用繼承調用出一個windows框框來

如果不使用繼承的話,需要調用一些復雜的命令

方法重載

在多態前要先了解一下方法重載(overload)和方法覆蓋(override)

思考一下:編寫一個名為Abc的類,能返回兩個整數中較大的一個

  • 若果是接收兩個float型的數,返回較大數
  • 如果是接收散了int型的數,返回最大數
 1 public class Demo3 {
 2     public static void main(String[] args) {
 3         Abc test1 = new Abc();
 4         System.out.println(test1.getMax(23, 78));
 5     }
 6 
 7 }
 8 
 9 class Abc
10 {
11     public int getMax(int i,int j)
12     {
13         if(i>j)
14         {
15             return i;
16         }
17         else
18         {
19             return j;
20         }
21     }
22 }
返回兩個整數中較大的數
 1 public class Demo3 {
 2     public static void main(String[] args) {
 3         Abc test1 = new Abc();
 4         Abc test2 = new Abc();
 5         System.out.println(test1.getMax(23, 78));
 6         System.out.println(test1.getMaxFloat(9.8f, 12.2f));
 7     }
 8 
 9 }
10 
11 class Abc
12 {
13     public int getMax(int i,int j)
14     {
15         if(i>j)
16         {
17             return i;
18         }
19         else
20         {
21             return j;
22         }
23     }
24     public float getMaxFloat(float a,float b)
25     {
26         if(a>b)
27         {
28             return a;
29         }
30         else
31         {
32             return b;
33         }
34     }
35 }
返回兩個小數中較大的一個

可以看出我們是又專門加一個,比較小數的成員方法,有沒有方法用一個方法來進行比較呢?

這個時候有可以利用方法重載的特性——可以定義重名的兩個成員方法,讓編譯器自己選擇用哪個?

 1 package com.xiaohui;
 2 /*
 3  * 作者:我聊啊
 4  * 時間:2018.9.11
 5  * 功能:了解方法重載
 6  */
 7 public class Demo3 {
 8     public static void main(String[] args) {
 9         Abc test1 = new Abc();
10         Abc test2 = new Abc();
11         System.out.println(test1.getMax(23, 78));
12         System.out.println(test1.getMax(9.8f, 12.2f));
13     }
14 
15 }
16 
17 class Abc
18 {
19     public int getMax(int i,int j)
20     {
21         if(i>j)
22         {
23             return i;
24         }
25         else
26         {
27             return j;
28         }
29     }
30     public float getMax(float a,float b)
31     {
32         if(a>b)
33         {
34             return a;
35         }
36         else
37         {
38             return b;
39         }
40     }
41 }
方法重載

方法重載的概念

  簡單地說:方法重載就是在類的同一種功能的多種實現方式,到底使用哪種方式,取決於調用者給出的參數。

注意事項

  1. 方法名一定相同
  2. 方法的參數類型,個數,順序至少有一項不同——(順序:(int a , double b)改成(double a , int b))
  3. 返回類型也可以不相同,但是如果只有返回類型不一樣,是不能夠構重載的
  4. 方法的訪問控制修飾符可以不同,如果只是修飾符不同,也是不能夠構成重載的

方法的覆蓋(重寫)

既然子類可以繼承父類的屬性和方法,這樣可以提高代碼的復用性,這個很好,可是問題來了!!

假設我要寫三個類——貓、狗、豬,顯然這三個都是動物,他們之間一定存在着相同的特點。根據類的抽象特征,我們可以把他們的相同點提取出來,形成一個父類Animal,然后繼承。

但是問題來了,動物都會叫,但是叫聲是不一樣的,怎樣解決子類和父類方法的異同!

這是就體現出了方法覆蓋(重寫)的特性了

 1 public class Demo4 
 2 {
 3     public static void main(String[] args) {
 4     Cat cat1 = new Cat();
 5     cat1.cry();
 6     
 7     Dog dog1 = new Dog();
 8     dog1.cry();
 9     }
10 
11 }
12 
13 class Animal
14 {
15     int age;
16     String name;
17     //動物都會叫
18     public void cry()
19     {
20         System.out.println("我是動物,不知道怎么叫");
21     }
22 }
23 class Cat extends Animal
24 {
25     //覆蓋了父類的方法
26     public void cry()
27     {
28         System.out.println("喵喵喵");
29     }
30 }
31 
32 class Dog extends Animal
33 {
34     //覆蓋了父類的方法
35     public void cry()
36     {
37         System.out.println("汪汪汪");
38     }
39 }
方法覆蓋——喵喵喵&汪汪汪

方法重寫的核心思想:子類的某些方法和父類不一樣,需要覆蓋掉父類的方法

方法覆蓋的概念

簡單的說:方法覆蓋就是子類有一個方法,和父類的某個方法的名稱、返回類型、參數一樣,那么我們就說子類的這個方法覆蓋了父類的那個方法。

注意事項

  1. 子類的方法的返回類型,參數,方法名稱要和父類方法的返回類型完全一致,否則編譯會出錯
  2. 子類方法不能縮小父類方法的訪問權限,換句話說子類的權限可以比父類高

多態

所謂多態,就是指一個引用(類型)在不同情況下的多種狀態。也可以這樣理解:多態是指通過指向父類的指針,來調用在不同子類中實現的方法

案例

 1 public class Demo6 
 2 {
 3     public static void main(String[] args) 
 4     {
 5         //多態
 6         Animal an;//創建了一個Animal類引用變量,Animal類引用就是以后可以用來指向Animal對象的對象引用
 7         an =new Cat();    //讓這個動物的引用指向了貓這個實例(對象)
 8         an.cry();
 9         an = new Dog();
10         //以Dog類為模板,在堆空間里創建一個Dog類對象,簡稱為Dog對象
11         an.cry();
12         //an這個引用會自動判斷引用是那種類型的
13     }
14 }
15 //動物類
16 class Animal
17 {
18     String name;
19     int age;
20     public String getName() {
21         return name;
22     }
23     public void setName(String name) {
24         this.name = name;
25     }
26     public int getAge() {
27         return age;
28     }
29     public void setAge(int age) {
30         this.age = age;
31     }
32     
33     //動物會叫
34     public void cry()
35     {
36         System.out.println("不知道怎么叫");
37     }
38     
39 }
40 class Cat extends Animal
41 {
42     //貓自己叫
43     public void cry()
44     {
45         System.out.println("喵喵喵");
46     }
47 }
48 class Dog extends Animal
49 {
50     //狗自己叫
51     public void cry()
52     {
53         System.out.println("汪汪汪");
54     }
55 }
56 
57 輸出結果:
58 喵喵喵
59 汪汪汪
多態

  如果沒有這個特性,狗要叫就要創建一個狗的引用,貓要叫就要創建一個貓的引用,動物再多一點就會不方便管理。當然多態也能調用孫子類的方法。

 

 1 package com.xiaohui;
 2 
 3 public class Demo7 
 4 {
 5     public static void main(String[] args) 
 6     {
 7         Master master = new Master();
 8         master.feed(new Dog(), new Bone());
 9         master.feed(new Cat(),new Fish());
10         //我想要他喂那種動物就喂那種懂我,我想喂他吃什么就吃什么
11         //
12     }
13 
14 }
15 //主人類
16 class Master
17 {
18     //給動物喂食物,使用多態,方法就可以用一個
19     public void feed(Animal an,Food f)
20     {
21         an.eat();
22         f.showName();
23     }
24 }
25 
26 class Food
27 {
28     String name;
29     public void showName()
30     {
31         
32     }
33 }
34 class Fish extends Food
35 {
36     public void showName()
37     {
38         System.out.println("魚");
39     }
40 }
41 class Bone extends Food
42 {
43     public void showName()
44     {
45         System.out.println("骨頭");
46     }
47 }
48 //動物類
49 class Animal
50 {
51     String name;
52     int age;
53     //動物會吃
54     public void  eat()
55     {
56         System.out.println("不知道吃什么");
57     }
58 }
59 
60 class Cat extends Animal
61 {
62     //貓進食
63     public void eat()
64     {
65         System.out.println("貓愛吃魚");
66     }
67 }
68 
69 class Dog extends Animal
70 {
71     //狗進食
72     public void eat()
73     {
74         System.out.println("狗愛吃骨頭");
75     }
76 }
想喂貓喂貓,想喂狗喂狗

  如果Food類和Animal類下的子類有許多的話,Master類中的方法是無需改變的,只需要輸入對應的動物和事物就可以了。否則我們想要狗吃骨頭和貓吃魚就要用這么多的代碼來寫

                Dog dog1 = new Dog();
		dog1.eat();
		Bone bone1 = new Bone();
		bone1.showName();

		Cat cat1 = new Cat();
		cat1.eat();
		Fish fish1 = new Fish();
		fish1.showName();    

引用的注意事項:

  1. Java允許父類的引用變量引用它的子類的對象(對象)
    Animal animal = new Cat()
    

    這種轉換是自動完成的  

  2. 類型轉換還有一些具體的細節要求,之后會進一步學醫,比如子類能不能轉換成父類,有什么要求等等...  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM