java中的多态关系的运用

1、多态发生的三个必备条件

  继承、重写、父类引用指向子类对象

2、注意

  当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

  方法的重写,也就是子类能够重写父类的方法

  当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。要想调用父类中被重写的方法,则必须使用关键字super。

3、好处

  可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

4、例子

 1 //父类
 2 package com.test.five;
 3 
 4 public class Parent {
 5     public void Test(){
 6         System.out.println("我 是 父类");
 7     }
 8 }
 9 
10 //子类一
11 package com.test.five;
12 
13 public class Child extends Parent {
14     public void Test(){
15         System.out.println("我 是大儿子");
16     }
17     public void Sex(){
18         System.out.println("我 是个男的");
19     }
20 }
21 //子类二
22 package com.test.five;
23 
24 public class Sister extends Parent{
25     public void Test(){
26         System.out.println("我也是个子类");
27     }
28     public void Sex(){
29         System.out.println("我是个女儿");
30     }
31 }
32 //测试类
33     package com.test.five;
34 
35 public class Test {
36     public static void main(String[] args) {
37         Parent p = new Child();
38         p.Test();//父类声明,子类创建,调用该对象的方法(子类父同时所拥有的方法)
39         Show(p);
40         Show(new Sister());
41         Show(new Child());
42     }
43     //测试类中的静态类方法,在测试类中可以直接调用此方法(不用再实例化类的对象)
44     public static void Show(Parent p){
45         p.Test();
46         if( p instanceof Child){
47             Child c = (Child)p;
48             c.Sex();
49         }else if(p instanceof Sister){
50             Sister s = (Sister)p;
51             s.Sex();
52         }
53     }
54 }

得出的结果是:

我 是大儿子
我 是大儿子
我 是个男的
我也是个子类
我是个女儿
我 是大儿子
我 是个男的

 5、注意(例子)

 1 //父类
 2 package com.test.six;
 3 
 4 public class Emploee {
 5     private String name;
 6     private String address;
 7     private int num;
 8     public Emploee(String name,String address,int num){
 9         System.out.println("Emploee的构造函数");
10         this.name = name;
11         this.address = address;
12         this.num = num;
13     }
14     public void check(){
15         System.out.println("Emploee中check的name:"+this.name+" ,address =  "+this.address);
16     }
17     public String toString(){
18         return name+"  "+address+"  "+num;
19     }
20     public String getName() {
21         return name;
22     }
23     public void setName(String name) {
24         this.name = name;
25     }
26     public String getAddress() {
27         return address;
28     }
29     public void setAddress(String address) {
30         this.address = address;
31     }
32     public int getNum() {
33         return num;
34     }
35 }
36 
37 //子类
38 package com.test.six;
39 
40 public class Salary extends Emploee {
41     private double salary;
42     //构造函数
43     public Salary(String name, String address, int num,double salary) {
44         super(name, address, num);
45         System.out.println("salary的构造函数");
46         setSalary(salary);
47     }
48     public double getSalary() {
49         return salary;
50     }
51 
52     public void setSalary(double salary) {
53         if(salary >=0.0){
54             this.salary = salary;
55         }
56     }    
57     public void check(){
58         System.out.println("这是salary的check的方法");
59         System.out.println("Salary中的name="+getName()+"  薪资="+getSalary());
60     }
61      public double computePay() {
62           System.out.println("计算工资,付给:" + getName());
63           return salary/52;
64        }
65 }
66 //测试类
67 package com.test.six;
68 
69 public class Test {
70     public static void main(String[] args) {
71         Salary s = new Salary("张三", "北京", 3, 8000.0);
72         Emploee e = new Salary("李四", "上海", 5, 10000.0);
73         System.out.println("salary对象引用中的方法调用");
74         s.check();
75         s.computePay();
76         System.out.println("emploee对象引用中的方法调用");
77         e.check();
78     }
79 }

得到的结果如下:

 1 Emploee的构造函数
 2 salary的构造函数
 3 Emploee的构造函数
 4 salary的构造函数
 5 salary对象引用中的方法调用
 6 这是salary的check的方法
 7 Salary中的name=张三  薪资=8000.0
 8 计算工资,付给:张三
 9 emploee对象引用中的方法调用
10 这是salary的check的方法
11 Salary中的name=李四  薪资=10000.0

----一旦实例化一个对象,其执行顺序,首先:

在不涉及继承的前提下,当首次加载类时,按照如下顺序执行:
1、按照出现顺序先后执行静态成员变量定义与静态块;
2、按照出现顺序先后执行动态成员变量定义与动态块;
3、执行构造函数;
4、再次实例化对象时只执行第2、4步即可;

在涉及到继承时,按照如下顺序执行:
1、执行父类的静态成员变量定义与静态块,执行子类的静态成员变量与静态块
2、执行父类非静态成员变量定义与动态块,执行父类构造方法;
3、执行子类的非静态成员变量定义与动态块,执行子类构造方法;
注意:父类构造方法中用到的方法如果已被子类重写,那么在构造子类对象时在
调用父类构造函数中使用子类重写的方法。

例子一:

package com.test.seven;

public class TestOne {
    private static TestOne t1 = new TestOne();
    //静态变量
    private static int i1;
    private static int i2 = 2;

    public TestOne(){
        i1++;
        i2++;
    }
    public static void main(String[] args) {
        TestOne t2 = new TestOne();
        System.out.println("t2.i1 = " +t2.i1);
        System.out.println("t2.i2 = "+t2.i2);    
    }
}

得到的结果如下:

t2.i1 = 2
t2.i2 = 3

执行过程:

  首先执行给t1、i1、i2分别给予初始值null,0,0,在执行TestOne t1 = new TestOne();
这样子i1++,i2++被执行,i1,i2都变成1,执行完毕后接着执行int i1 ,  i1,i2的值仍然是1,1,当执行int i2=2时,i2被赋予了值,即i1=1,i2=2;再执行
TestOne t2 = new TestOne(),i1,i2在执行++,此时i1=2,i2=3,输出i1,i2,结果就是:t2.i1=2,t2.i2=3通过上面代码可以知道:
系统默认的给予比通过等号的赋予先执行。

例子二:

package com.test.seven;

public class TestOne {
    private static TestOne t1 = new TestOne();
    //静态变量
    private static int i1;
    private static int i2 = 2;
    //静态块
    static{
        System.out.println("静态块");
    }
    //动态块
    {
        System.out.println("动态块");
    }
    public TestOne(){
        i1++;
        System.out.println("i1--------------"+i1);
        i2++;
        System.out.println("i2--------------"+i2);
    }
    public static void main(String[] args) {
        TestOne t2 = new TestOne();
        System.out.println("t2.i1 = " +t2.i1);
        System.out.println("t2.i2 = "+t2.i2);
        
    }
}

得到的结果如下:

1 动态块
2 i1--------------1
3 i2--------------1
4 静态块
5 动态块
6 i1--------------2
7 i2--------------3
8 t2.i1 = 2
9 t2.i2 = 3

 

posted @ 2016-05-30 18:00  FanSunny  阅读(1369)  评论(0编辑  收藏  举报