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. 类型转换还有一些具体的细节要求,之后会进一步学医,比如子类能不能转换成父类,有什么要求等等...  

 

posted @ 2018-09-08 16:30  Igniculus  阅读(1497)  评论(0编辑  收藏  举报