java学习笔记——第10章 多态、包装类、内部类和枚举类(一)

10.1多态
何为多态
多态(polumorphism)性是面向对象程序设计代码的一个重要机制。java语言的多态总是子类型的多态。 在面向对象中,通常把多态分为两大类(特定的、通用的),四个小类(强制的、重载的、参数的、包含的),如图:
在这里插入图片描述
在这样一个体系中,多态表现为多种形式的能力。
通用的多态:引用有相同结构类型的大量对象,他们有共同的特性。
特定的多态:小部分没有相同特征的对象。
强制的:一种隐式实现类型转换的方法。
重载的:将一个标志符用作多个意义。
参数的:为不同类型的参数提供相同的操作。
包含的:类包含关系的抽象操作。

(1)强制的多态:强制多态隐式将参数按照某种方法,转换成编译器认为正确的类型已避免错误。

2.0+2.0
2.0+2
2.0+2

第一个表达式将两个double操作数相加。
第二个表达式编译器隐式的将第二个操作数转换为double型。
第三个表达式,编译器将double转换成String类型,并将它们串联。

C c=new C();
Derived derived=new Derived();
c.m( derived );

在方法调用中,假设类Derived继承了Base,类C有一个原型为m(Base)的方法,则编译器隐式的将类Derived的对象derived转换为类Base的对象。这种隐式的转换使方法m(Base)使用所有能转换成Base类的所有参数。

(2)重载的多态:例如“+”在上面程序有两个意思,一是两个double型数相加,二是表示两个串相连。这些运算符的重载依赖于编译器根据上下文做出的选择。但不支持用户定义的操作符重载。
Java支持用户定义的函数重载,在一个类中可以有相同名字的方法,但方法可以有不同的参数。

(3)参数的多态:参数多态允许把许多类型抽象成单一的表示。例如在一个名为List的抽象类中,描述了一组具有同样特征的对象,提供一个通用的模板,可以通过指定一种类型以重用这个抽象类。

(4)包含的多态:包含多态是通过值的类型和集合的包含关系实现了多态的行为。

演示java中的多态
例子:

//定义基类jiBaseClass
class jiBaseClass {
    public int book = 6;

    public void base() {
        System.out.println("老邓头说:父类的普通方法:");
    }

    public void test() {
        System.out.println("父类的被覆盖的方法:");
    }
}

public class duptai extends jiBaseClass {
    public String book = "<青年公寓>";

    public void test() {
        System.out.println("子类的覆盖父类的方法:");// 子类中重写方法test()
    }

    public void sub() {
        System.out.println("子类的普通方法:");
    }

    public static void main(String args[]) {
        //下面编译时类型和运行时类型一样,因此不存在多态
        jiBaseClass bc = new jiBaseClass();
        System.out.println(bc.book);
        //下面两次调用将执行jiBaseCase方法
        bc.base();
        bc.test();

        //下面编译时类型和运行时类型一样,因此不存在多态
        duptai sc = new duptai();
        System.out.println(sc.book);
        //下面调用将执行从父类继承的base方法
        sc.base();
        //下面调用将执行当前类的text方法
        sc.test();
        //下面调用将执行当前类的sub方法
        sc.sub();
        
        //下面编译时类型和运行时类型不一样,多态发生
        jiBaseClass ploymophicBc = new duptai();
        System.out.println(ploymophicBc.book);
        //下面调用将执行从父类继承的base方法
        ploymophicBc.base();
        //下面调用将执行当前类的sub方法
        ploymophicBc.test();

        //jiBaseClass类没有提供sub方法,因为sanYin的编译类型是jiBaseClass
        //所以下面代码编译时会出错
        //sanYin.sub()
    }
}

结果:

6
老邓头说:父类的普通方法:
父类的被覆盖的方法:
<青年公寓>
老邓头说:父类的普通方法:
子类的覆盖父类的方法:
子类的普通方法:
6
老邓头说:父类的普通方法:
子类的覆盖父类的方法:

第三个引用变量ploymophicBc,编译时类型是jiBaseClass,运行时类型是duptai,所以ploymophicBc.book是父类中的,ploymophicBc.base()是父类中的,ploymophicBc.test()因为子类重写了,所以用子类重写的!
因为:
编写代码时,只能调用父类中具有的方法,如果子类重写了该方法,运行时实际调用的是运行时类型的该方法。

(------------------------------------------------------------------------------------------------------------------)
补充一下:编译类型和运行类型

class Father {
	Father() {
		System.out.println("父类构造器");
	}
	public void doWork() {
		System.out.println("父类doWork方法");
	}
}
class son extends Father {
	son() {
		System.out.println("子类构造器");
	}
	public void doWork() {
		System.out.println("子类doWork方法");
	}
 
}
public class runORbian {
	public static void main(String[] args) {
		Father child = new son();
		child.doWork();
	}
}

其中代码段:

Father child = new son();

child这个引用变量的Father类就是编译类型,而 new son()则是运行类型
在程序运行时,首先会调用父类构造器,再调用子类构造器。在编译时,就会自动检查引用变量child的编译类型中是否包含doWork方法,很明显,在父类中有doWork方法(如果没有会报错),但是,在JVM运行时,由于在子类中覆盖了doWork方法,所以child实际运行时,是调用了子类的doWork方法,而不是父类的,这也就是多态的一种(运行时多态)。
原话是:引用变量在编译阶段只能调用其编译时类型所具有的方法,但在运行时则去执行它运行时类型所具有的方法
编写代码时,只能调用父类中具有的方法,如果子类重写了该方法,运行时实际调用的是运行时类型的该方法。
(------------------------------------------------------------------------------------------------------------------)

再举个例子:
代码:


class Father {
    int a=100;
	public void doWork() {
		System.out.println("父类doWork方法");
	}
    public void test() {
		System.out.println("父类test方法子类没有");
	}
}
 
class son extends Father {
    int a=99;
	public void doWork() {
		System.out.println("子类重写了的doWork方法");
	}
    public void noone() {
		System.out.println("子类noone方法");
	}
}
public class runORbian {
	public static void main(String[] args) {
 
		Father child = new son();
        System.out.println(child.a);
		child.doWork();
        child.test();
	}
}

输出结果:

100
子类重写了的doWork方法  
父类test方法子类没有

其中100是父类中的,即使子类重写,但他不是方法。
第二个输出是因为子类重写了父类的方法。
第三个输出是因为子类没有父类的方法。
子类中noone函数输出不了是因为父类中没有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值