java运行时多态编译时多态
⑴ 1. 编译时的多态性与运行时的多态性有什么区别,他们的实现方法有什么不同
多态从实现的角度可以划为两类:编译时多态和运行时多态。
编译时的多态性:就是在程序编译的时候,也就是生成解决方案的时候就决定要实现什么操作。
运行时的多态性:就是指直到系统运行时,才根据实际情况决定实现何种操作。
1、多态实现形式不同:
编译时的多态是通过静态连编来实现的;运行时的多态是用动态连编来实现的。
2、多态性通过方式不同:
编译时的多态性主要是通过函数重载和运算符重载来实现的;运行时的多态性主要是通过虚函数来实现的。
(1)java运行时多态编译时多态扩展阅读:
静态多态性又称编译时的多态性。静态多态性的函数调用速度快、效率高但缺乏灵活性,在程序运行前就应决定执行的函数和方法。
动态多态性的特点是:不在编译时确定调用的是哪个函数,而是在程序运行过程中才动态地确定操作所针对的对象。又称运行时的多态性。动态多态性是通过虚函数(virtual function)实现的。
⑵ 关于Java的编译时多态和运行时多态
您想的有点复杂化了,简单的说吧,您说的运行时的多态是分为可执行文件和非可执行文件,也就是说您的程序打没打包,而您说的编译时的多态也分为两种;1、重载。2、继承。前者是静态的多态形式也就是说不可以用于多个类;针对方法,后者是可以在多个类之间使用,要记得只可以子类继承父类,不可‘以下犯上’。就像是java中的类型,一个是private,另一个是public。
⑶ 什么是多态实现多态的机制是什么
面试官:什么是多态呢?
猪队友:多种形态,气体,液体,固体~
面试官:go out! now!
到底什么是多态呢?
允许将子类类型的指针赋值给父类类型的指针,把不同的子类对象都当作父类来看。比如你家有亲属结婚了,让你们家派个人来参加婚礼,邀请函写的是让你爸来,但是实际上你去了,或者你妹妹去了,这都是可以的,因为你们代表的是你爸,但是在你们去之前他们也不知道谁会去,只知道是你们家的人。可能是你爸爸,可能是你们家的其他人代表你爸参加。这就是多态。
多态又分为 编译时多态和运行时多态。
编译时多态:比如重载
运行时多态:比如重写
简单版本:
原理也很简单,父类或者接口定义的引用变量可以指向子类或者具体实现类的实例对象,由于程序调用方法是在运行期才动态绑定的,那么引用变量所指向的具体实例对象在运行期才确定。所以这个对象的方法是运行期正在内存运行的这个对象的方法而不是引用变量的类型中定义的方法。
术语版本:
我们将引入Java静态分派和动态分派这个概念。
如果想深入的同学可以参考可以参考《深入理解Java虚拟机》。
参考:
https://blog.csdn.net/sunxianghuang/article/details/52280002
⑷ JAVA的多态有什么特点什么地方适合使用多态
多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。
如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的(就像电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用电池供电或者用交流电,甚至还有可能是太阳能,A系统只会通过B类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。
方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。
⑸ 运行时多态和编译时多态
多态:多态的概念比较简单,就是同一操作作用于不同的对象,可以有不同的解释,产生不同
的执行结果。
运行时多态:重写就是一种运行时多态。只有在运行过程中才能清楚调用的是具体的那个方法。
重写的情况:
public class Dog {
public void bark(){
System.out.println("woof ");
}
private static class Hound extends Dog{
public void sniff(){
System.out.println("sniff ");
}
public void bark(){
System.out.println("bowl"); }
}
public static void main(String [] args){
Dog dog = new Hound();
dog.bark();
Dog dog1=new Dog();
dog1.bark();
}
}
输出结果是:
bowl
woof
父类引用指向子类对象情况:
public class Parent{
public void call(){
sout("im Parent");
}
}
public class Son extends Parent{// 1.有类继承或者接口实现
public void call(){// 2.子类要重写父类的方法
sout("im Son");
}
}
public class Daughter extends Parent{// 1.有类继承或者接口实现
public void call(){// 2.子类要重写父类的方法
sout("im Daughter");
}
}
public class Test{
public static void main(String[] args){
Parent p = new Son(); //3.父类的引用指向子类的对象
Parent p1 = new Daughter(); //3.父类的引用指向子类的对象
p.call();
p1.call();
}
}
输出结果是:
im son
im Daughter
同样是 Parent 类的实例,p.call 调用的是 Son 类的实现、p1.call 调用的是 Daughter 的实现。这里因为是自己定义的,所以可以在new对像的过程中就能明白p是son,p1是daughter。但是有的时候,我们无法直观看到new对象的过程。比如说工厂模式、Spring的ioc。所以只有在程序运行的过程才能够清楚具体调用的是谁的方法。
编译时多态:Java中重载就是一种编译时多态。程序处在编译期间,通过参数的不同来决定具体调用的是那个方法。
思考:重载一定是发生在同一个类中吗?子类是否可重载父类的方法?
⑹ java中多态性什么意思
多态性:顾名思义就是拥有“多种形态”的含义,是指属性或方法在子类中表现为多种形态。
在JAVA中有两种多态是指:运行时多态和编译时多态。多态性是面向对象的核心特征之一,类的多态性提供类中成员设计的灵活性和方法执行的多样性。
多态指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
扩展资料:
多态的好处:
1、可替换性(substitutability)多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2、可扩充性(extensibility)多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。
3、接口性(interface-ability)多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4、灵活性(flexibility)它在应用中体现了灵活多样的操作,提高了使用效率。
5、简化性(simplicity)多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
⑺ 谈谈你对Java中的多态的理解.(为什么要使用多态,有什么好处,一般用在什么场合)
面向对象编程有三大特性:封装、继承、多态。
封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。
继承是为了重用父类代码。两个类若存在IS-A的关系就可以使用继承。,同时继承也为实现多态做了铺垫。
那么什么是多态呢?多态的实现机制又是什么?请看我一一为你揭开:
所谓多态
就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
比如你是一个酒神,对酒情有独钟。某日回家发现桌上有几个杯子里面都装了白酒,从外面看我们是不可能知道这是些什么酒,只有喝了之后才能够猜出来是何种酒。你一喝,这是剑南春、再喝这是五粮液、再喝这是酒鬼酒….在这里我们可以描述成如下:
酒 a = 剑南春
酒 b = 五粮液
酒 c = 酒鬼酒
…
这里所表现的的就是多态。剑南春、五粮液、酒鬼酒都是酒的子类,我们只是通过酒这一个父类就能够引用不同的子类,这就是多态——我们只有在运行的时候才会知道引用变量所指向的具体实例对象。
诚然,要理解多态我们就必须要明白什么是“向上转型”。在继承中我们简单介绍了向上转型,这里就在啰嗦下:在上面的喝酒例子中,酒(Win)是父类,剑南春(JNC)、五粮液(WLY)、酒鬼酒(JGJ)是子类。我们定义如下代码:
JNC a = new JNC();
对于这个代码我们非常容易理解无非就是实例化了一个剑南春的对象嘛!但是这样呢?
Wine a = new JNC();
在这里我们这样理解,这里定义了一个Wine 类型的a,它指向JNC对象实例。由于JNC是继承与Wine,所以JNC可以自动向上转型为Wine,所以a是可以指向JNC实例对象的。这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。
但是向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们。所以父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在与子类中的方法和属性它就望尘莫及了。
publicclassWine{
publicvoidfun1(){
System.out.println("Wine的Fun.....");
fun2();
}
publicvoidfun2(){
System.out.println("Wine的Fun2...");
}
}
publicclassJNCextendsWine{
/**
*@desc子类重载父类方法
*父类中不存在该方法,向上转型后,父类是不能引用该方法的
*@parama
*@returnvoid
*/
publicvoidfun1(Stringa){
System.out.println("JNC的Fun1...");
fun2();
}
/**
*子类重写父类方法
*指向子类的父类引用调用fun2时,必定是调用该方法
*/
publicvoidfun2(){
System.out.println("JNC的Fun2...");
}
}
publicclassTest{
publicstaticvoidmain(String[]args){
Winea=newJNC();
a.fun1();
}
}
-------------------------------------------------
Output:
Wine的Fun.....
JNC的Fun2...
从程序的运行结果中我们发现,a.fun1()首先是运行父类Wine中的fun1().然后再运行子类JNC中的fun2()。
分析:在这个程序中子类JNC重载了父类Wine的方法fun1(),重写fun2(),而且重载后的fun1(String a)与 fun1()不是同一个方法,由于父类中没有该方法,向上转型后会丢失该方法,所以执行JNC的Wine类型引用是不能引用fun1(String a)方法。而子类JNC重写了fun2() ,那么指向JNC的Wine引用会调用JNC中fun2()方法。
所以对于多态我们可以总结如下:
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。
对于面向对象而已,多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。
多态的实现
2.1实现条件
在刚刚开始就提到了继承在为多态的实现做了准备。子类Child继承父类Father,我们可以编写一个指向子类的父类类型引用,该引用既可以处理父类Father对象,也可以处理子类Child对象,当相同的消息发送给子类或者父类对象时,该对象就会根据自己所属的引用而执行不同的行为,这就是多态。即多态性就是相同的消息使得不同的类做出不同的响应。
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
2.2实现形式
在Java中有两种形式可以实现多态。继承和接口。
2.2.1、基于继承实现的多态
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。
publicclassWine{
privateStringname;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicWine(){
}
publicStringdrink(){
return"喝的是"+getName();
}
/**
*重写toString()
*/
publicStringtoString(){
returnnull;
}
}
publicclassJNCextendsWine{
publicJNC(){
setName("JNC");
}
/**
*重写父类方法,实现多态
*/
publicStringdrink(){
return"喝的是"+getName();
}
/**
*重写toString()
*/
publicStringtoString(){
return"Wine:"+getName();
}
}
publicclassJGJextendsWine{
publicJGJ(){
setName("JGJ");
}
/**
*重写父类方法,实现多态
*/
publicStringdrink(){
return"喝的是"+getName();
}
/**
*重写toString()
*/
publicStringtoString(){
return"Wine:"+getName();
}
}
publicclassTest{
publicstaticvoidmain(String[]args){
//定义父类数组
Wine[]wines=newWine[2];
//定义两个子类
JNCjnc=newJNC();
JGJjgj=newJGJ();
//父类引用子类对象
wines[0]=jnc;
wines[1]=jgj;
for(inti=0;i<2;i++){
System.out.println(wines[i].toString()+"--"+wines[i].drink());
}
System.out.println("-------------------------------");
}
}
OUTPUT:
Wine:JNC--喝的是JNC
Wine:JGJ--喝的是JGJ
在上面的代码中JNC、JGJ继承Wine,并且重写了drink()、toString()方法,程序运行结果是调用子类中方法,输出JNC、JGJ的名称,这就是多态的表现。不同的对象可以执行相同的行为,但是他们都需要通过自己的实现方式来执行,这就要得益于向上转型了。
我们都知道所有的类都继承自超类Object,toString()方法也是Object中方法,当我们这样写时:
Objecto=newJGJ();
System.out.println(o.toString());
输出的结果是Wine : JGJ。
Object、Wine、JGJ三者继承链关系是:JGJ—>Wine—>Object。所以我们可以这样说:当子类重写父类的方法被调用时,只有对象继承链中的最末端的方法才会被调用。但是注意如果这样写:
Objecto=newWine();
System.out.println(o.toString());
输出的结果应该是Null,因为JGJ并不存在于该对象继承链中。
所以基于继承实现的多态可以总结如下:对于引用子类的父类类型,在处理该引用时,它适用于继承该父类的所有子类,子类对象的不同,对方法的实现也就不同,执行相同动作产生的行为也就不同。
如果父类是抽象类,那么子类必须要实现父类中所有的抽象方法,这样该父类所有的子类一定存在统一的对外接口,但其内部的具体实现可以各异。这样我们就可以使用顶层类提供的统一接口来处理该层次的方法。
2.2.2、基于接口实现的多态
继承是通过重写父类的同一方法的几个不同子类来体现的,那么就可就是通过实现接口并覆盖接口中同一方法的几不同的类体现的。
在接口的多态中,指向接口的引用必须是指定这实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。
继承都是单继承,只能为一组相关的类提供一致的服务接口。但是接口可以是多继承多实现,它能够利用一组相关或者不相关的接口进行组合与扩充,能够对外提供一致的服务接口。所以它相对于继承来说有更好的灵活性。
⑻ java中多态是什么意思
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,
父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数实现的。
多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的。C++中的多态性具体体现在运行和编译两个方面。
运行时多态是动态多态,其具体引用的对象在运行时才能确定。编译时多态是静态多态,在编译时就可以确定对象使用的形式。
多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
C++中,实现多态有以下方法:虚函数,抽象类,覆盖,模板(重载和多态无关)。
OC中的多态:不同对象对同一消息的不同响应.子类可以重写父类的方法
多态就是允许方法重名 参数或返回值可以是父类型传入或返回。
(8)java运行时多态编译时多态扩展阅读:
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
赋值之后,父类型的引用就可以根据当前赋值给它的子对象的特性以不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲。
比如从某个基类派生出多个子类,其基类有一个虚方法Tdoit,然后其子类也有这个方法,但行为不同,然后这些子类对象中的任何一个可以赋给其基类对象的引用,或者说将子对象地址赋给基类指针,这样其基类的对象就可以执行不同的操作了。
实际上你是在通过其基类的引用来访问其子类对象的,你要做的就是一个赋值操作。
使用继承性的结果就是当创建了一个类的家族,在认识这个类的家族时,就是把子类的对象当作基类的对象,这种认识又叫作upcasting(向上转型)。这样认识的重要性在于:我们可以只针对基类写出一段程序,但它可以适应于这个类的家族,
因为编译器会自动找出合适的对象来执行操作。这种现象又称为多态性。而实现多态性的手段又叫称动态绑定(dynamic binding)。
⑼ java的多态怎么理解啊,多态有什么用途。
1. Java中除了static和final方法外,其他所有的方法都是运行时绑定的。private方法都被隐式指定为final的,因此final的方法不会在运行时绑定。当在派生类中重写基类中static、final、或private方法时,实质上是创建了一个新的方法。
2.在派生类中,对于基类中的private方法,最好采用不同的名字。
3.包含抽象方法的类叫做抽象类。注意定义里面包含这样的意思,只要类中包含一个抽象方法,该类就是抽象类。抽象类在派生中就是作为基类的角色,为不同的子类提供通用的接口。
4.对象清理的顺序和创建的顺序相反,当然前提是自己想手动清理对象,因为大家都知道Java垃圾回收器。
5.在基类的构造方法中小心调用基类中被重写的方法,这里涉及到对象初始化顺序。
6.构造方法是被隐式声明为static方法。
7.用继承表达行为间的差异,用字段表达状态上的变化。
在JAVA中有两种多态是指:运行时多态和编译时多态。
关于类的多态性简介如下:
多态(polymorphism)意为一个名字可具有多种语义.在程序设计语言中,多态性是指”一种定义,多种实现”.例如,运算符+有多种含义,究竟执行哪种运算取决于参加运算的操作数类型:
1+2 //加法运算符
“1” + “2” //字符串连接运算,操作数是字符串
多态性是面向对象的核心特征之一,类的多态性提供类中成员设计的灵活性和方法执行的多样性.
1、类多态性表现
(1)方法重载
重载表现为同一个类中方法的多态性.一个类生命多个重载方法就是为一种功能提供多种实现.编译时,根据方法实际参数的数据类型\个数和次序,决定究竟应该执行重载方法中的哪一个.
(2)子类重定义从父类继承来的成员
当子类从父类继承来的成员不适合子类时,子类不能删除它们,但可以重定义它们,使弗雷成员适应子类的新需求.子类重定义父类成员,同名成员在父类与子类之间表现出多态性,父类对象引用父类成员,子类对象引用子类成员,不会产生冲突和混乱.
子类可重定义父类的同名成员变量,称子类隐藏父类成员变量.子类也可以重定义父类的同名成员方法,当子类方法的参数列表与父类方法参数列表完全相同时,称为子类方法覆盖(override)父类方法。覆盖父类方法时,子类方法的访问权限不能小于父类方法的权限。
由于Object类的equals()方法比较两个对象的引用是否相等而不是值是否相等,因此一个类要覆盖Object类的equals()方法,提供本类两个对象比较相等方法.
覆盖表现为父类与子类之间方法的多态性.java 寻找执行方法的原则是:从对象所属的类开始,寻找匹配的方法执行,如果当前类中没有匹配的方法,则逐层向上依次在父类或祖先类中寻找匹配方法,直到Object类.
2、super 引用
在子类的成员方法中,可以使用代词super引用父类成员.super引用的语法如下:
super([参数列表]) //在子类的构造方法体中,调用父类的构造方法
super.成员变量 //当子类隐藏父类成员变量时,引用父类同名成员变量
super.成员方法([参数列表]) //当子类覆盖父类成员方法时,调用父类同名成员方法
*注意:super引用没有单独使用的语法
3、多态性有两种:
1)编译时多态性
对于多个同名方法,如果在编译时能够确定执行同名方法中的哪一个,则称为编译时多态性.
2)运行时多态性
如果在编译时不能确定,只能在运行时才能确定执行多个同名方法中的哪一个,则称为运行时多态性.
方法覆盖表现出两种多态性,当对象获得本类实例时,为编译时多态性,否则为运行时多态性,例如:
XXXX x1 = new XXXX(参数列表); //对象获得本类实例,对象与其引用的实例类型一致
XXX xx1 = new XXX(参数列表);
x1.toString(); //编译时多态性,执行XXX类的方法.
xx1.toString(); //编译时多态性,执行XXXX类覆盖的方法.
XXXX为XXX的父类.
由于子类对象既是父类对象,父类对象与子类对象之间具有赋值相容性,父类对象能够被赋值为子类对象.例如,
XXXX x2 = new XXX(参数列表); //父类对象获得子类实例,子类对象即是父类对象
x2.toString(); //运行时多态
x2声明为父类对象却获得子类XXX的实例,那么x2.toString()究竟执行父类方法还是执行子类覆盖的方法呢?
这分为两种情况:
取决于子类是否覆盖父类方法.如果子类覆盖父类方法,则执行子类方法;
如果没有覆盖,则执行父类方法.
在编译时,仅仅依据对象所属的类,系统无法确定到底应该执行那个类的方法,只有运行时才能确定,因此这是运行时多态.
父类对象并不能执行所有的子类方法,只能执行那些父类中声明\子类覆盖的子类方法.
在这样一个体系中,多态表现出多种形式的能力。通用多态引用有相同结构类型的大量对象,他们有着共同的特征。特定的多态涉及的是小部分没有相同特征的对象。四种多态可做以下描述:
强制的:一种隐式做类型转换的方法。
重载的:将一个标志符用作多个意义。
参数的:为不同类型的参数提供相同的操作。
包含的:类包含关系的抽象操作。
我将在讲述子类型多态前简单介绍一下这几种多态。
强制的多态
强制多态隐式的将参数按某种方法,转换成编译器认为正确的类型以避免错误。在以下的表达式中,编译器必须决定二元运算符‘+’所应做的工作:
2.0 + 2.0
2.0 + 2
2.0 + "2"
第一个表达式将两个double的操作数相加;Java中特别声明了这种用法。
第二个表达式将double型和int相加。Java中没有明确定义这种运算。不过,编译器隐式的将第二个操作数转换为double型,并作double型的加法。做对程序员来说十分方便,否则将会抛出一个编译错误,或者强制程序员显式的将int转换为double。
第三个表达式将double与一个String相加。Java中同样没有定义这样的操作。所以,编译器将double转换成String类型,并将他们做串联。
强制多态也会发生在方法调用中。假设类Derived继承了类Base,类C有一个方法,原型为m(Base),在下面的代码中,编译器隐式的将 Derived类的对象derived转化为Base类的对象。这种隐式的转换使m(Base)方法使用所有能转换成Base类的所有参数。
C c = new C();
Derived derived = new Derived();
c.m( derived );
并且,隐式的强制转换,可以避免类型转换的麻烦,减少编译错误。当然,编译器仍然会优先验证符合定义的对象类型。
重载的多态
重载允许用相同的运算符或方法,去表示截然不同的意义。‘+’在上面的程序中有两个意思:两个double型的数相加;两个串相连。另外还有整型相加, 长整型,等等。这些运算符的重载,依赖于编译器根据上下文做出的选择。以往的编译器会把操作数隐式转换为完全符合操作符的类型。虽然Java明确支持重 载,但不支持用户定义的操作符重载。
Java支持用户定义的函数重载。一个类中可以有相同名字的方法,这些方法可以有不同的意义。这些重载的方法中,必须满足参数数目不同,相同位置上的参数类型不同。这些不同可以帮助编译器区分不同版本的方法。
编译器以这种唯一表示的特征来表示不同的方法,比用名字表示更为有效。据此,所有的多态行为都能编译通过。
强制和重载的多态都被分类为特定的多态,因为这些多态都是在特定的意义上的。这些被划入多态的特性给程序员带来了很大的方便。强制多态排除了麻烦的类型和编译错误。重载多态像一块糖,允许程序员用相同的名字表示不同的方法,很方便。
参数的多态
参数多态允许把许多类型抽象成单一的表示。例如,List抽象类中,描述了一组具有同样特征的对象,提供了一个通用的模板。你可以通过指定一种类型以重 用这个抽象类。这些参数可以是任何用户定义的类型,大量的用户可以使用这个抽象类,因此参数多态毫无疑问的成为最强大的多态。
乍一 看,上面抽象类好像是java.util.List的功能。然而,Java实际上并不支持真正的安全类型风格的参数多态,这也是 java.util.List和java.util的其他集合类是用原始的java.lang.Object写的原因(参考我的文章"A Primordial Interface?" 以获得更多细节)。Java的单根继承方式解决了部分问题,但没有发挥出参数多态的全部功能。Eric Allen有一篇精彩的文章“Behold the Power of Parametric Polymorphism”,描述了Java通用类型的需求,并建议给Sun的Java规格需求#000014号文档"Add Generic Types to the Java Programming Language."(参考资源链接)
包含的多态
包含多态通过值的类型和集合的包含关系实现了多态的行为.在包括Java在内的众多面向对象语言中,包含关系是子类型的。所以,Java的包含多态是子类型的多态。
在早期,Java开发者们所提及的多态就特指子类型的多态。通过一种面向类型的观点,我们可以看到子类型多态的强大功能。以下的文章中我们将仔细探讨这个问题。为简明起见,下文中的多态均指包含多态。
1个行为,不同的对象,他们具体体现出来的方式不一样,
比如:方法重载 overloading 以及 方法重写(覆盖)override
class Human{
void run(){输出 人在跑}
}
class Man extends Human{
void run(){输出 男人在跑}
}
这个时候,同是跑,不同的对象,不一样(这个是方法覆盖的例子)
class Test{
void out(String str){输出 str}
void out(int i){输出 i}
}
这个例子是方法重载,方法名相同,参数表不同
ok,明白了这些还不够,还用人在跑举例
Human ahuman=new Man();
这样我等于实例化了一个Man的对象,并声明了一个Human的引用,让它去指向Man这个对象
意思是说,把 Man这个对象当 Human看了.
比如去动物园,你看见了一个动物,不知道它是什么, "这是什么动物? " "这是大熊猫! "
这2句话,就是最好的证明,因为不知道它是大熊猫,但知道它的父类是动物,所以,
这个大熊猫对象,你把它当成其父类 动物看,这样子合情合理.
这种方式下要注意 new Man();的确实例化了Man对象,所以 ahuman.run()这个方法 输出的是 "男人在跑 "
如果在子类 Man下你 写了一些它独有的方法 比如 eat(),而Human没有这个方法,
在调用eat方法时,一定要注意 强制类型转换 ((Man)ahuman).eat(),这样才可以...
对接口来说,情况是类似的...
⑽ 请问一下Java里编译时多态和运行时多态的区别,最好举个例,谢谢
个人看法
多态的概念 父类引用指向子类对象 而实际调用的方法为子类的方法。
编译时多态 Java里叫重载 严格来说不叫多态 运行时多态 有继承 有重写 父类引用指向子类对象
例子我看就算了 书上多 的是