Java基础-面向对象第三大特性之多态(polymorphism)

                Java基础-面向对象第三大特性之多态(polymorphism)

                                      作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

 

一.多态概述

  多态是继封装,继承之后,面向对象的第三大特性,多态的前提是继承。

  从现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三即是学生也是人。即出现两种形态。Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

  最终多态体现为父类引用变量可以指向子类对象。多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。

 

二.多态调用的三种形式

  多态调用方法,方法必须运行子类的重写!

1>.多态的定义格式:就是父类的引用变量指向子类对象。

1 父类类型  变量名 = new 子类类型();
2 变量名.方法名();

2>.普通类多态定义的格式

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 class Father{
 8     public void show(){
 9         System.out.println("父类的show方法!");
10     }
11 }
12 
13 class Son extends Father{
14     public void show(){
15         System.out.println("子类重写父类的show方法!");
16     }
17 }
18 
19 public class MyInterfaceDemo{
20     public static void main(String[] args){
21         //Java中,对象的多态性,调用公式:“父类类型或者接口类型  变量  =  new 子类对象();”
22         Father f = new Son();
23         f.show();
24     }
25 }
26 
27 
28 
29 /*
30 以上代码执行结果如下:
31 子类重写父类的show方法!
32 */

3>.抽象类多态定义的格式

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 abstract class Father{
 8     public abstract void eat();
 9 }
10 
11 class Son extends Father{
12     public void eat(){
13         System.out.println("儿子喜欢吃米饭!");
14     }
15 }
16 
17 public class MyInterfaceDemo{
18     public static void main(String[] args){
19         //抽象类Father,子类是Son
20         Father f = new Son();
21         f.eat();
22     }
23 }
24 
25 
26 
27 /*
28 以上代码执行结果如下:
29 儿子喜欢吃米饭!
30 */

4>.接口多态定义格式

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 interface  Father{
 8     public abstract void smoking();
 9 }
10 
11 class Son implements Father{
12     public void smoking(){
13         System.out.println("儿子会抽烟!");
14     }
15 }
16 
17 public class MyInterfaceDemo{
18     public static void main(String[] args){
19         //接口Father,实现类Son
20         Father f = new Son();
21         f.smoking();
22     }
23 }
24 
25 
26 
27 /*
28 以上代码执行结果如下:
29 儿子会抽烟!
30 */

 

三.多态中成员变量的特点

1>.成员变量(编译运行全看父类)

  a>.编译的时候,参考父类中有没有这个变量,如果有,编译成功,没有则编译失败;

  b>.运行的时候,运行的是父类中的变量值;

2>.成员方法(编译看父类,运行看子类

  a>.编译的时候,参考父类中有没有这个方法,如果有,编译成功,没有则编译失败

  b>.运行的时候,运行的是子类的重写方法;

3>.静态成员方法

  没有多态性。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 class  Father{
 8     int age = 30;
 9     public void show(){
10         System.out.println("Father的方法");
11     }
12 }
13 
14 class Son extends Father{
15     int age = 8;
16     public void show(){
17         System.out.println("Son的方法");
18     }
19 }
20 
21 public class MyInterfaceDemo{
22     public static void main(String[] args){
23         Father f = new Son();
24         System.out.println(f.age);
25         f.show();
26     }
27 }
28 
29 
30 
31 /*
32 以上代码执行结果如下:
33 30
34 Son的方法
35 */

 

四.instanceof关键字

   我们了解多态之后,会发现一个对象的数据类型不一定会保持不变。当我们想要确定一个对象是否是某个类时,就会用到比较运算符,只不过它很特殊,不能赢大于小于或是等于号直接进行判断,而是要用到关键字,即instanceof,它只能用作比较引用数据类型,用来比较一个引用类型的变量,是不是这个类型的对象。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6  
 7 abstract class Person{
 8     public abstract void sleep();
 9 }
10 
11 
12 class Student extends Person{
13     public void sleep(){
14         System.out.println("学生在休息!");
15     }
16 }
17 
18 class Teacher extends Person{
19     public void sleep(){
20         System.out.println("老师在休息!");
21     }
22 }
23 
24 public class PersonDemo{
25     public static void main(String[] args){
26         
27         Person p = new Student();
28         
29         p = new Teacher();
30         
31         boolean flag = p instanceof Student;
32         
33         System.out.println("引用数据类型'p'是否为Student类型:>>> " + flag);
34     
35         p.sleep();
36     }
37 }
38 
39 
40 
41 
42 /*
43 以上代码执行结果如下:
44 引用数据类型'p'是否为Student类型:>>> false
45 老师在休息!
46 */

 

五.多态转型

1>.多态的向上转型

   多态常见的就是自动类型提升,将取值范围小的,自动提升为取值范围大的。范围小的,看成是子类,范围大的看成父类。

优点:

  这样做的好出就是可以调用子类父类的公共属性(方法)。

缺点:

  无法调用子类特有的属性(方法)。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6  
 7 abstract class Person{
 8     public abstract void sleep();
 9 }
10 
11 
12 class Student extends Person{
13     public void sleep(){
14         System.out.println("学生在休息!");
15     }
16 }
17 
18 class Teacher extends Person{
19     public void sleep(){
20         System.out.println("老师在休息!");
21     }
22 }
23 
24 public class PersonDemo{
25     public static void main(String[] args){
26         
27         //从子类对象往父类变量赋值(自动类型提升,向上转型)
28         Person p = new Student();
29         
30     }
31 }

2>.多态的向下转型

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6  
 7 abstract class Person{
 8     public abstract void sleep();
 9 }
10 
11 
12 class Student extends Person{
13     public void sleep(){
14         System.out.println("学生在休息!");
15     }
16 }
17 
18 class Teacher extends Person{
19     public void sleep(){
20         System.out.println("老师在休息!");
21     }
22 }
23 
24 public class PersonDemo{
25     public static void main(String[] args){
26         
27         //从子类对象往父类变量赋值(自动类型提升,向上转型)
28         Person p = new Student();
29         
30         
31         //从父类类型转向子类类型(向下转型)
32         Student s  = (Student)p; 
33 
34     }
35 }

3>.多态转型的案例

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 abstract class Animal{
 8     public abstract void eat();
 9 }
10 
11 class Cat extends Animal{
12     public void eat(){
13         System.out.println("猫吃猫粮!");
14     }
15     
16     public void catchMouse(){
17         System.out.println("猫抓老鼠!");
18     }
19 }
20 
21 class Dog extends Animal{
22     public void eat(){
23         System.out.println("狗吃狗粮!");
24     }
25     
26     public void run(){
27         System.out.println("狗能跑!");
28     }
29 }
30 
31 public class AnimalDemo{
32     public static void main(String[] args){
33         //两个子类,使用两次多态调用
34         Animal a1 = new Cat();
35         Animal a2 = new Dog();
36         //a1,a2调用子类父类共有方法,运行走子类的重写方法
37         a1.eat();
38         a2.eat();
39         /*类型向下转型,强制转换,调用子类的特有,防止发生异常,
40         a1属于CatUI小,转成Cat类,a2属于Dog对象,转成Dog类,我们
41         可以用关键字instanceof判断。
42         */
43         if(a1 instanceof Cat){
44             Cat c = (Cat)a1;
45             c.catchMouse();
46         }
47         
48         if(a2 instanceof Dog){
49             Dog d = (Dog)a2;
50             d.run();
51         }
52         
53     }
54 }
55 
56 
57 /*
58 以上代码执行结果如下:
59 猫吃猫粮!
60 狗吃狗粮!
61 猫抓老鼠!
62 狗能跑!
63 */

 

六.匿名对象

1>.匿名对象的概念   

  匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6  
 7 class Person{
 8     public void eat(){
 9         System.out.println("人是铁,饭是钢,一顿不吃饿得慌!");
10     }
11 }
12 
13 
14 public class PersonDemo{
15     public static void main(String[] args){
16         
17         //有名字的对象,引用类型变量,可以反复使用eat方法。
18         Person p = new Person();
19         p.eat();
20         
21         //匿名对象,没有引用变量,只能使用一次,如果你再通过new调用eat方法的话实际上是又新生成了一个对象。
22         new Person().eat();
23         new Person().eat();
24         
25     }
26 }

2>.匿名对象的特点

  a>.创建匿名对象直接使用,没有变量名;

  b>.匿名对象在没有指定其引用变量时,只能使用一次;

  c>.匿名对象可以作为方法接受的参数,方法返回值使用;

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6  
 7 class Person{
 8     public void eat(){
 9         System.out.println("人是铁,饭是钢,一顿不吃饿得慌!");
10     }
11 }
12 public class PersonDemo{
13     public static void main(String[] args){
14         //有名字的对象,引用类型变量,可以反复使用eat方法。
15         Person p = new Person();
16         p.eat();
17         //匿名对象,没有引用变量,只能使用一次,如果你再通过new调用eat方法的话实际上是又新生成了一个对象。
18         new Person().eat();
19         new Person().eat();
20         method(p);
21         
22         //匿名方法当实参
23         method(new Person());        
24         p = method();
25         method(p);
26     }
27     //方法的返回值是Person类型,方法的return语句,返回的是这个类的对象。就可以用匿名对象来实现。
28     public static Person method(){
29         return new Person();
30     }
31     //调用方法method,传递Person类型对象
32     public static void method(Person p){
33         p.eat();
34     }
35 }
36 
37 
38 
39 /*
40 以上代码执行结果如下:
41 人是铁,饭是钢,一顿不吃饿得慌!
42 人是铁,饭是钢,一顿不吃饿得慌!
43 人是铁,饭是钢,一顿不吃饿得慌!
44 人是铁,饭是钢,一顿不吃饿得慌!
45 人是铁,饭是钢,一顿不吃饿得慌!
46 人是铁,饭是钢,一顿不吃饿得慌!
47 */

 

七.内部类

1>.内部类概念

  a>.什么是内部类

    将类写在其它类的内部,可以写在其它类的成员位置和局部位置,这时写在其它类内部的类成为内部类,其它类也称为外部类。

  b>.什么时候使用内部类

    在描述事物时,若一个事物内部还包含其它可能包含的事物,比如在描述汽车时,汽车中还包含这发动机,这时发动机就可以使用内部类来描述。

  c>.内部类分类

    内部类分为成员内部类和局部内部类。我们定义内部类时,就是一个正常定义类的过程,同样包含各种修饰符,继承与实现关系等。在内部类中可以直接访问外部类的所有成员。

2>.成员内部类的调用格式

  内部类可以使用外部类成员,包括私有变量。外部类要使用内部类的成员,必须建立内部类对象。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 class Outer{
 8     private int a = 100;
 9     class Inner{
10         public void inner(){
11             System.out.println("内部类方法inter " + a);
12         }
13     }
14 }
15 
16 public class InnerClassDemo{
17     public static void main(String[] args){
18         //创建内部类对象in
19         Outer.Inner  in = new Outer().new Inner();
20         //调用内部类方法
21         in.inner();
22     }
23 }
24 
25 
26 /*
27 以上代码执行结果如下:
28 内部类方法inter 100
29 */

3>.成员内部类的同名变量调用

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 class Outer{
 8     int a = 100;
 9     class Inner{
10         int a = 200;
11         public void inner(){
12             int a = 300;
13             System.out.println("内部类局部变量(内部类成员方法)访问:>>> "+ a);
14             System.out.println("内部类成员变量访问:>>> "+ this.a);
15             System.out.println("外部类成员变量访问:>>> "+ Outer.this.a);
16         }
17     }
18 }
19 
20 public class InnerClassDemo{
21     public static void main(String[] args){
22         //创建内部类对象in
23         Outer.Inner  in = new Outer().new Inner();
24         //调用内部类方法
25         in.inner();
26     }
27 }
28 
29 
30 /*
31 以上代码执行结果如下:
32 内部类局部变量(内部类成员方法)访问:>>> 300
33 内部类成员变量访问:>>> 200
34 外部类成员变量访问:>>> 100
35 */

3>.局部内部类

  局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 class Outer{
 8     public void out(){
 9         class Inner{
10             public void inner(){
11                 System.out.println("局部内部类方法!");
12             }
13         }
14         //创建我们定义的Inner对象
15         Inner in = new Inner();        
16         //调用创建好的对象的方法,这样不管谁只要能调用out方法就会触发调用Inner类中的inner()方法啦!
17         in.inner();
18     }
19 }
20 
21 public class InnerClassDemo{
22     public static void main(String[] args){
23         new Outer().out();
24     }
25 }
26 
27 
28 /*
29 以上代码执行结果如下:
30 局部内部类方法!
31 */

4>.匿名内部类

  a>.匿名内部类概念

    内部类是为了应对更为复杂的类间关系。查看源代码中会涉及到,而在日常业务中很难遇到,这里不做赘述。最长用到的内部类就是匿名内部类,它是局部内部类的一种。定义的匿名内部类有两个含义:第一,临时定义某一指定类型的子类;第二,定义后即刻创建刚刚定义的这个子类的对象。

  b>.定义匿名内部类的作用与格式

    匿名内部类是创建某个子类对象的快捷方式。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 interface  Smoking{
 8     public abstract void smoking();
 9 }
10 
11 public class  SmokingDemo{
12     public static void main(String[] args){
13         //这就是用匿名对象实现接口并调用接口中的方法,切记不要忘记调用smoking()了哟!
14         new Smoking(){
15             public void smoking(){
16                 System.out.println("运维不喜欢吸烟!");
17             }
18         }.smoking();
19     }
20 }
21 
22 /*
23 以上代码执行结果如下:
24 运维不喜欢吸烟!
25 */

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值