java重载与多态
java中方法重载

java中方法重载方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
调用重载方法时,Java编译器能通过检查调用的方法的参数类型和个数选择一个恰当的方法。
方法重载通常用于创建完成一组任务相似但参数的类型或参数的个数不同的方法。
java中重载与重写的区别首先我们来讲讲:重载(Overloading)(1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。
多个同名函数同时存在,具有不同的参数个数/类型。
重载Overloading是一个类中多态性的一种表现。
(2) Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。
调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。
(3) 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。
无法以返回型别作为重载函数的区分标准。
下面是重载的例子:package c04.answer;//这是包名//这是这个程序的第一种编程方法,在main方法中先创建一个Dog类实例,然后在Dog 类的构造方法中利用this关键字调用不同的bark方法。
不同的.重载方法bark是根据其参数类型的不同而区分的。
//注意:除构造器以外,编译器禁止在其他任何地方中调用构造器。
package c04.answer;public class Dog {Dog(){this.bark();}void bark()//bark()方法是重载方法{System.out.println(\ no barking!\this.bark(\ female\ , 3.4);}void bark(String m,double l)//注意:重载的方法的返回值都是一样的,{System.out.println(\ a barking dog!\this.bark(5, \ China\}void bark(int a,String n)//不能以返回值区分重载方法,而只能以参数类型和类名来区分{System.out.println(\ a howling dog\}public static void main(String[] args){Dog dog = new Dog();//dog.bark(); [Page]//dog.bark(\ male\ , \ yellow\//dog.bark(5, \ China\然后我们再来谈谈重写(Overriding)(1) 父类与子类之间的多态性,对父类的函数进行重新定义。
java重载方法的特征

java重载方法的特征Java的重载方法是指在同一个类中定义了多个方法,它们具有相同的名称但是不同的参数列表。
重载方法在Java中是一种多态性的体现,它允许我们使用相同的方法名来调用不同的方法。
重载方法具有以下的特征:1.方法名相同:重载方法的名称必须相同。
2.参数列表不同:重载方法的参数列表必须不同,可以是参数类型不同、参数个数不同或参数顺序不同。
3.返回类型可以相同也可以不同:重载方法的返回类型可以相同,也可以不同。
唯一的限制是不能仅仅通过返回类型的不同来进行方法的重载。
4.可以有不同的访问修饰符:重载方法可以有不同的访问修饰符,比如public、private或protected。
5.可以抛出不同的异常:重载方法可以抛出不同的异常,也可以不抛出异常。
重载方法的使用有以下的优点和特点:1.提高代码的可读性:通过使用重载方法,可以使用相同的方法名来表达不同的意义,这使得代码更加直观和易于理解。
2.简化编程:通过使用重载方法,可以避免定义大量类似的方法,从而简化了代码的编写过程。
3.提高代码的可维护性:重载方法使得代码更加模块化,当需要修改某个功能时,只需要修改对应的方法,而无需修改其他方法,这提高了代码的可维护性。
4.增加灵活性:通过使用重载方法,可以根据不同的参数类型或参数个数进行适应性的操作,从而增加了代码的灵活性。
在使用重载方法时,需要注意以下几点:1.不能仅仅通过返回类型的不同来进行方法的重载,因为Java编译器无法根据返回类型来确定具体调用哪个方法。
2.当重载方法的参数列表中有继承关系的参数类型时,需要注意参数类型的匹配规则。
例如,如果有一个重载方法的参数类型为Object,而另一个重载方法的参数类型为String,当调用方法时传入一个String对象时,编译器会优先选择参数类型为String的方法,而不会选择参数类型为Object的方法,因为String是Object的子类。
3.在重载方法中,参数个数和参数类型越多,重载方法的区分度就越高。
Java基本概念:多态

Java基本概念:多态⼀、简介描述:多态性是⾯向对象编程中的⼀个重要特性,主要是⽤来实现动态联编的。
换句话说,就是程序的最终状态只有在执⾏过程中才被决定,⽽⾮在编译期间就决定了。
这对于⼤型系统来说能提⾼系统的灵活性和扩展性。
多态允许相同类域的不同对象对同⼀消息做出响应。
即同⼀消息可以根据发送对象的不同⽽采⽤多种不同的⾏为⽅式。
多态可以让我们不⽤关⼼某个对象到底是什么具体类型,就可以使⽤该对象的某些⽅法,从⽽实现更加灵活的编程,提⾼系统的可扩展性。
如果对象的编译时类型和运⾏时类型不⼀致,就会造成多态。
存在条件:1. 类之间有继承关系。
2. ⼦类重写⽗类⽅法。
3. ⽗类引⽤指向⼦类对象。
注意:多态是⽅法的多态,属性没有多态性。
⼀个对象的实际类型是确定的,但是可以指向这个对象的引⽤的类型,却是可以是这对象实际类型的任意⽗类型。
⼦类继承⽗类,调⽤⽅法,如果该⽅法在⼦类中没有重写,那么就是调⽤的是⼦类继承⽗类的⽅法,如果重写了,那么调⽤的就是重写之后的⽅法。
'protected'修饰的⽗类⽅法可以被⼦类见到,也可以被⼦类重写,但是它是⽆法被外部所引⽤的,所以没有多态性。
通过⼀个变量调⽤其引⽤的对象的⼀个⽅法,编译器是否能让其编译通过,主要是看该变量类型的类中有没有定义该⽅法,如果有则编译通过,如果没有则编译报错。
⽽不是看这个变量所引⽤的对象中有没有该⽅法。
Java中的⽅法调⽤,是运⾏时动态和对象绑定的,不到运⾏的时候,是不知道到底哪个⽅法被调⽤的。
编写程序时,如果想调⽤运⾏时类型的⽅法,只能进⾏类型转换,不然通不过编译器的检查。
但是如果两个没有关联的类进⾏强制转换,会报类型转换异常:ClassCastException。
⽰例:public class Test {public static void main(String[] args) {/* 编译看左,运⾏看右 */Student student = new Student();/* 变量person是可以指向Person类型或其⼦类型的对象,所以可以指向Student类型对象 */Person person = new Student();/* 变量student能调⽤的⽅法是Student类中有的⽅法(包括继承过来的) */student.say();//Student/* 变量person能调⽤的⽅法是Person类中有的⽅法 */person.say();//Student}}class Person {public void say() {System.out.println("Person");}}class Student extends Person {public void say() {System.out.println("Student");}}⼆、重写、重载、多态的关系1. 重载是编译时多态调⽤重载的⽅法,在编译期间就要确定调⽤的⽅法是谁,如果不能确定则编译报错。
在JAVA中有两种多态指的是什么

同问 在JAVA中有两种多态指的是什么 2009-01-15 14:32 提问者: mdydyy |浏览次数:2218次
我来帮他解答
精彩回答
2009-01-15 15:11在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()究竟执行父类方法还是执行子类覆盖的方法呢? 这分为两种情况: 取决于子类是否覆盖父类方法.如果子类覆盖父类方法,则执行子类方法; 如果没有覆盖,则执行父类方法. 在编译时,仅仅依据对象所属的类,系统无法确定到底应该执行那个类的方法,只有运行时才能确定,因此这是运行时多态. 父类对象并不能执行所有的子类方法,只能执行那些父类中声明\子类覆盖的子类方法.
java多态演讲ppt

sram实现多态三个条件:
1:继承 2:重写(重写父类继承的方法) 3:父类引用指向字类对象
sramwww.
安博思软
多态的实现:通过继承实现
JAVA中,一个类之能有一个父类,不能多继承。一个父类可 以有多个子类,而在子类里可以重写父类的方法,这样每个子
sramwww.
安博思软
sramwww.
安博思软
多态性有两种:
编译时多态性(静态绑 定)
运行时多态性(动态 绑定)
如果在编译时不能确定,只能 , 在运行时才能确定执行多个 同名方法中的哪一个,则称为 运行时多态性。
对于多个同名方法,如果在编 译时能够确定执行同名方法 中的哪一个,则称为编译时多 态性。
sramwww.
安博思软
多态的实现:通过接口实现
继承 单继承 一个类只能继承一个父类! 一个类只能继承一个父类!
接口
多实现
一个类可以同时实现多个接口! 类可以同时实现多个接口! 同时实现多个接口
一个接口类型变量也可以指向其实现类的实例,这也是 个接口类型变量也可以指向其实现类的实例,这也是
输出结果:
我知道错了,别打了! 为什么打我?我做错什么了! 我跑,你打不着!
//子类3 public class Son3 extends Father{ //重写父类打孩子方法 public void hitChild(){ System.out.println("我跑,你打不着!"); }}
//子类1 public class Son1 extends Father{ //重写父类打孩子方法 public void hitChild(){ System.out.println("我知道错了,别打了!"); }}
java中级笔试题及答案2020

java中级笔试题及答案20201. 题目一:Java 基础问题:请写出Java中实现多态的三种方式。
答案:在Java中实现多态主要有以下三种方式:1. 方法重载(Overloading):在同一个类中定义多个同名方法,但参数列表不同。
2. 方法重写(Overriding):子类覆盖父类的方法,子类方法与父类方法具有相同的方法名、返回类型和参数列表。
3. 接口实现:通过实现接口中的方法来实现多态。
2. 题目二:Java 集合框架问题:简述ArrayList和LinkedList的区别。
答案:ArrayList和LinkedList都是实现了List接口的集合类,它们的区别主要体现在:1. ArrayList是基于动态数组实现的,而LinkedList是基于双向链表实现的。
2. ArrayList在随机访问时速度更快,因为链表需要从头开始遍历。
3. LinkedList在添加和删除元素时速度更快,因为链表可以直接在任意位置添加或删除节点。
4. LinkedList比ArrayList更占内存,因为LinkedList需要存储额外的节点指针。
3. 题目三:Java 异常处理问题:请解释Java中的checked异常和unchecked异常的区别。
答案:Java中的异常分为checked异常和unchecked异常:1. Checked异常:编译器在编译时会检查的异常,必须在方法声明中使用throws关键字抛出或在方法体内使用try-catch语句捕获处理。
2. Unchecked异常:编译器不会检查的异常,包括RuntimeException及其子类。
它们在运行时才会被抛出,不需要在方法声明中使用throws关键字。
4. 题目四:Java 线程问题:描述Java中实现线程同步的两种方式。
答案:Java中实现线程同步主要有两种方式:1. 使用synchronized关键字:可以修饰方法或代码块,确保同一时间只有一个线程执行该段代码。
java 多态笔试题

当然,我可以给你提供一些关于Java多态的笔试题。
请注意,以下问题仅供参考。
1. 什么是Java中的多态性?
2. 如何实现多态性?
3. 什么是动态绑定(Dynamic Binding)?
4. Java中的重写(Overriding)和重载(Overloading)的区别是什么?
5. 简要解释一下抽象类和接口的作用,并比较它们之间的异同点。
6. 能否在Java中创建一个抽象类的实例?为什么?
7. 是否可以同时使用final和abstract关键字修饰一个类或方法?为什么?
8. 什么是向上转型(Upcasting)和向下转型(Downcasting)?它们在多态中的作用是什么?
9. 请解释一下Java中的instanceof关键字的作用和用法。
10. 在Java中如何实现方法的重载?
这些问题应该可以帮助你巩固对Java多态的理解。
请记住,理论知识和实际编程经验相结合是非常重要的。
祝你好运!如果你有其他问题,请随时提问。
重载和多态的区别

重载和多态的区别多态性也是面向对象方法的一个重要特性.多态性是指在在程序中出现的"重名"现象,即在一个程序中相同的名字可以表示不同的实现.在JAVA中,多态性主要表现在如下两个方面:1方法重载.通常指在同一个类中,相同的方法名对应着不同的方法实现,但是方法的参数不同.2成员覆盖.通常指在不同类父类和子类中,允许有相同的变量名,但是数据类型不同;也允许有相同的方法名,但是对应的方法实现不同.在重载的情况下,同一类中具有相同的名字的方法.如何选择它的方法体呢?不能使用类名来区分,通常采用不同的方法形参表,区分重载要求形参在类型,个数和顺序的不同,在定义重载方法时,应在方法的形参的类型,个数和顺序有所不同,以便在选择时能够区别开来.在覆盖的情况下,同名的方法存在于不同的类中,在调用方法只要指明其方法所归属的类名就可以了.例如class Shape {void draw {}void erase {}}class Circle extends Shape {void draw {System.out.println"Circle.draw";}void erase {System.out.println"Circle.erase"; }}class Square extends Shape {void draw {System.out.println"Square.draw";}void erase {System.out.println"Square.erase";}}class Triangle extends Shape {void draw {System.out.println"Triangle.draw";}void erase {System.out.println"Triangle.erase";}}public class Test {public static Shape randShape {switchintMath.random * 3 {default:case 0: return new Circle;case 1: return new Square;case 2: return new Triangle;} }public static void mainString[] args {Shape[] s = new Shape[9];forint i = 0; i < s.length; i++ s[i] = randShape;forint i = 0; i < s.length; i++ s[i].draw;}}输出结果Triangle.drawCircle.drawTriangle.drawTriangle.drawTriangle.drawSquare.drawSquare.drawTriangle.drawCircle.drawTriangle.eraseCircle.eraseTriangle.eraseTriangle.eraseTriangle.eraseSquare.eraseSquare.eraseTriangle.eraseCircle.erasePress any key to continue...又一次执行Triangle.drawTriangle.drawCircle.drawCircle.drawCircle.drawTriangle.drawTriangle.drawSquare.drawCircle.drawTriangle.eraseTriangle.eraseCircle.eraseCircle.eraseCircle.eraseTriangle.eraseTriangle.eraseSquare.eraseCircle.erasePress any key to continue...两次执行结果不同的原因是其中的Math.random这个类导致的,math.random得到的数是0-1之间的随机数.写到这里,我突然想到了方法重载,那么它和多态,覆盖有什么区别呢?到GOOGLE是搜素了一下,不少.不过,最重要的一点区别是:通过方法重载进而实现对象的多态性.方法重载是指功能相同的多个方法使用同一个方法名.同名的多个方法的参数要有所不同,即在参数类型,参数个数和参数顺序上要有所区别,以便作为选择某个方法的根据.通常只有功能相同的方法进行重载才有意义.例如:计算两个数之和的重载方法定义如下:int addint i,int j{retrun i+j;}float addfloat i,float j{retrun i+j;}double adddouble i,double j{retrun i+j;}重载方法的选择通常是在编译时进行.系统根据不同的参数类型,个数或顺序,寻找最佳匹配方法.方法类型不参与匹配.下面是搜到的一些例子.public class Base{int a,b;public Baseint x,int y{a = x;b = y;}public int add{return a + b;}public void addint x,int y{int z;z = x + y;}}上面这段代码就是重载~~~他有三个特征1:方法名必须一样“add“。
java练习题及答案

练习题1.分别写出类、接口的关键字及对应继承关键字类的关键字:class接口的关键字:interface继承关键字:extends2.简要介绍方法的重载和覆盖的区别1、方法的覆盖是子类和父类之间的关系,是垂直关系;方法的重载是同一个类中方法之间的关系,是水平关系。
2、覆盖只能由一个方法,或只能由一对方法产生关系;方法的重载是多个方法之间的关系。
3、覆盖要求参数列表相同;重载要求参数列表不同。
4、覆盖关系中,调用那个方法体,是根据对象的类型(对象对应存储空间类型)来决定;重载关系,是根据调用时的实参表与形参表来选择方法体的。
3.什么是前期绑定?后期绑定?前期绑定;对于方法的重载,在程序编译时,根据调用语句中给出的参数,就可以决定在程序执行时调用同名方法的那个版本。
后期绑定:对于方法的覆盖,要在程序执行时,才能决定同名方法的版本。
4.方法重载的条件是?1.参数列表不同2.与返回类型无关3.函数名(方法名)相同5.Java中多态包括(方法的重载)、(方法的覆盖)。
6.解释import java.awt.*的含义。
引入awt这个包里所有的类7.修饰词final、static、abstract可以分别两两组合修饰类(F)8.Java是多继承(F)9.含有抽象方法的类就是接口(F)含有抽象方法的类是抽象类10.解释隐藏和覆盖隐藏:子类的成员变量和超类的成员变量同名时,超类的成员变量被隐藏。
覆盖:子类的成员方法和超类的成员方法同名时,超类的成员方法被子类的成员方法覆盖。
11.小应用程序公共类的类名可以与文件名不同名。
(F)12.小应用程序的公共类必须是(java.applet.Applet)的子类13.小应用程序中无main( )方法,它的执行比Application程序复杂。
(F)14.用javac编译appletfirst.java小应用程序后,用最少的代码写出aa.html内的文档内容,并写出执行aa.html的命令。
继承、多态,重载、重写的区别与总结

继承、多态,重载、重写的区别与总结李氏原则:(1)父类的引用指向子类对象。
-多态(2)接口的引用指向实现类的实例。
-接口Polo咯,什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承、多态、重载和重写继承(inheritance)简单的说,继承就是在一个现有类型的基础上,通过增加新的方法或者重定义已有方法(下面会讲到,这种方式叫重写)的方式,产生一个新的类型。
继承是面向对象的三个基本特征--封装、继承、多态的其中之一,我们在使用JAVA 时编写的每一个类都是在继承,因为在JAVA语言中,ng.Object类是所有类最根本的基类(或者叫父类、超类),如果我们新定义的一个类没有明确地指定继承自哪个基类,那么JAVA就会默认为它是继承自Object类的。
我们可以把JAVA中的类分为以下三种:类:使用class定义且不含有抽象方法的类。
抽象类:使用abstract class定义的类,它可以含有,也可以不含有抽象方法。
接口:使用interface定义的类。
在这三种类型之间存在下面的继承规律:类可以继承(extends)类,可以继承(extends)抽象类,可以继承(implements)接口。
抽象类可以继承(extends)类,可以继承(extends)抽象类,可以继承(implements)接口。
接口只能继承(extends)接口。
请注意上面三条规律中每种继承情况下使用的不同的关键字extends和implements,它们是不可以随意替换的。
大家知道,一个普通类继承一个接口后,必须实现这个接口中定义的所有方法,否则就只能被定义为抽象类。
我在这里之所以没有对implements关键字使用“实现”这种说法是因为从概念上来说它也是表示一种继承关系,而且对于抽象类implements接口的情况下,它并不是一定要实现这个接口定义的任何方法,因此使用继承的说法更为合理一些。
【面向对象设计的3个基本特征】

【⾯向对象设计的3个基本特征】JAVA中⾯向对象的三⼤特征:⾯向对象具有继承性(Inheritance)⾯向对象具有多态性(Polymorphism)⾯向对象具有封装性(Encapsulation)⼀、继承多个类具有共同的属性(成员变量)与⾏为(成员⽅法)的时候,将这些共同的部分抽取出来定义到⼀个公共的类中,其他及各类可以与这个公共的类形成继承关系,从⽽在多个类中不需要重复定义公共部分!这个公共的类就是⽗类,也称为超类或者基类,其他的类就是⼦类。
⼦类可以直接访问⽗类的⾮私有化成员变量,访问⽗类的私有化成员变量可以使⽤super.get()⽅法。
1、 Java继承的特点:A、Java只存在单个继承不存在多个继承,即:⼀个类只能有⼀个⽗类B、Java可以多层继承,多重继承2、Java继承的优点A、继承是基于存在多个重复代码的时候提出的,那么继承能很好的提⾼复⽤率!B、使类与类之间存在继承关系,是实现多态操作的前提!C、继承关键字:extends3、Java继承的缺点继承使得多个类之间具有了⼦⽗类关系,当⼀个类存在多个⼦类的时候,如果⽗类发⽣变化,那么这些⼦类会跟着⼀同变化,造成类与类之间的“强耦合”关系!4、Java继承注意点A、不要仅仅为了获取某个类的某个功能⽽去继承这个类B、类与类之间要存在所属关系,不能够随意继承例:⼈与狗都具有吃饭的动作,狗为了实现吃饭的动作,⽽继承⼈,这是不合适的!所谓的所属关系是is--a的关系,也就是说AAA is BB 的....学⽣是⼈的某⼀个群体,可以同时具有吃饭的动作5、何时使⽤继承A、具有公共的属性与⾏为操作的时候,提⾼复⽤性B、具有is--a的所属关系的类与类之间6、类的主要组成部分的⼦⽗类继承关系中的特点!A、成员变量a、继承关系中同名的⼦类成员变量、局部变量、⽗类的成员变量这三者之间使⽤顺序:在具有相同变量名的这种情况下,不使⽤this、super等关键字进⾏调⽤时,即成员变量前什么都不写,调⽤顺序按照由局部变量位置---当前类成员变量位置---⽗类成员变量位置依次进⾏查找变量,什么位置先有值,就会使⽤这个值!调⽤⽅式:this,superB、成员⽅法a、继承中的成员⽅法使⽤顺序:当⼦类具有与⽗类同名成员⽅法时,进⾏调⽤过程中不使⽤this、super等关键字,即成员⽅法前什么都不写,⽅法的有效顺序:当前类的成员⽅法---⽗类的成员⽅法⼦类中有⽅法实现,则按照⼦类的实现进⾏,若在⼦类中使⽤super调⽤了⽗类的⽅法,那么⽗类⽅法也要执⾏!但是默认成员⽅法内是没有super调⽤的!!!b、重写概念:⼦类中出现与⽗类⼀模⼀样的⽅法时,会出现⼦类⽅法将⽗类⽅法覆盖的情况,这种情况成为重写或者复写c、重写注意事项- ⽗类中的私有⽅法不可以被重写,覆盖!- ⼦类重写⽗类⽅法后,继续使⽤⽗类的⽅法时候,可以使⽤super调⽤- 重写时,⼦类的⽅法的访问权限要⼤于或者等于⽗类成员⽅法的访问权限- 静态⽅法只能被静态⽅法覆盖- ⼦类对于⽗类的功能有增强需求的时候,可以重写⽗类的⽅法以增强其功能!d、重写与重载的区别重写:⼦⽗类之间,⽅法完全相同(返回值、⽅法名、参数列表),但是⼦⽗类之间的⽅法体必须不同,否则没有意义!重载:同⼀个类中,⽅法名相同,参数列表不同,与返回值⽆关!(参数列表:包括两项:参数个数,对应参数的数据类型)重载何时使⽤:当⼀个类中需要完成某个相同功能,但是⽅法的参数不同需要分别进⾏操作时!C、构造⽅法a、⼦类中所有的构造⽅法默认都访问⽗类中⽆参构造b、每个构造⽅法的第⼀⾏是super();super(参数列表);如果把这两⾏代码放在⾮第⼀⾏位置会报错c、根据构造⽅法的特性,在⼿动给出任意⼀个构造⽅法的时候,之前默认的⽆参构造会被覆盖,此时具有继承关系的时候,⼦类之前默认存在的每个构造都调⽤⽆参构造super()失效,此时必须在每个构造⽅中⼿动给出super(参数列表)的⽅式直接或间接调⽤之前⼿动在⽗类中给出的构造!d、构造⽅法执⾏了⼀定会创建相应对象吗?不⼀定,当具有继承关系的类时,⼦类创建对象的时候会调⽤⽗类的构造⽅法,⽤来初始化⽗类的成员变量,这个时候⽗类的构造执⾏了,但是内存中并没有⽗类的对象!e、构造⽅法是否可以被重写或者继承?不可以,因为构造⽅法名需要与类名相同,假如出现继承或者重写关系,就会有⼦类中有⼀个与⽗类的类名相同的构造⽅法,但是⼜由于构造⽅法需要与类名相同,此时⼦类类名需要与构造相同,这个时候就会出现⽗类与⼦类的类名相同,⽗类类名==构造⽅法名==⼦类类名,不能存在同名的类!⼆、多态java程序中定义的引⽤变量所指向的具体类型和通过该引⽤类型发出的⽅法在调⽤时不确定,该引⽤变量发出的⽅法到底调⽤哪个类的实现的⽅法,必须在程序运⾏期间才能决定,这就是多态。
java方法重载和重写

java方法重载和重写方法重载:就是在同一个类中,方法的名字相同,但参数个数、参数的类型或返回值类型不同!方法重写:它是指子类和父类的关系,子类重写了父类的方法,但方法名、参数类型、参数个数必须相同!Java方法的重写与重载一、方法的重写。
1、重写只能出现在继承关系之中。
当一个类继承它的父类方法时,都有机会重写该父类的方法。
一个特例是父类的方法被标识为final。
重写的主要优点是能够定义某个子类型特有的行为。
class Animal {public void eat(){System.out.println ( Animal is eating.}}class Horse extends Animal{public void eat(){System.out.println ( Horse is eating.}}2、对于从父类继承来的抽象方法,要么在子类用重写的方式设计该方法,要么把子类也标识为抽象的。
所以抽象方法可以说是必须要被重写的方法。
3、重写的意义。
重写方法可以实现多态,用父类的引用来操纵子类对象,但是在实际运行中对象将运行其自己特有的方法。
public class Test {public static void main (String[] args) {Animal h = new Horse();h.eat();}}class Animal {public void eat(){System.out.println ( Animal is eating.}}class Horse extends Animal{public void eat(){System.out.println ( Horse is eating.}public void buck(){}}一个原则是:使用了什么引用,编译器就会只调用引用类所拥有的方法。
如果调用子类特有的方法,如上例的h.buck(); 编译器会抱怨的。
java高级工程师面试题及答案

java高级工程师面试题及答案一、Java基础知识1. 请简述Java语言的特点和优势。
Java是一种跨平台的编程语言,具有以下特点和优势:- 简单易学:Java采用C/C++风格的语法,使得开发者可以快速上手。
- 面向对象:Java是一种面向对象的语言,通过封装、继承和多态等特性,使得程序更加模块化、可复用和可维护。
- 平台无关性:Java应用程序可以在不同的操作系统平台上运行,只需编译一次即可。
- 高效性能:Java通过垃圾回收机制和即时编译器(Just-In-Time Compiler)来提高性能,同时拥有高度优化的运行时环境。
- 安全性:Java提供了安全的执行环境,通过类加载器、字节码验证和安全管理器等机制,防止恶意代码的执行。
2. 什么是Java的自动装箱和拆箱?自动装箱(Autoboxing)和拆箱(Unboxing)是Java编译器提供的便利功能。
- 自动装箱:将基本数据类型转换为对应的包装类对象,例如将int 类型转换为Integer对象。
- 自动拆箱:将包装类对象转换为基本数据类型,例如将Integer对象转换为int类型。
自动装箱和拆箱使得基本数据类型和包装类之间的转换更加方便,可以在需要包装类的地方直接使用基本数据类型,编译器会自动进行装箱或拆箱操作。
3. 请简述Java中的重载和重写的区别。
- 重载(Overload):指在同一个类中,方法名相同但参数列表不同的多个方法,可以具有不同的返回类型。
重载可以通过参数个数、类型或顺序的不同来实现。
重载的方法可以拥有不同的访问修饰符。
- 重写(Override):指在子类中重新定义父类的方法,方法名、参数列表和返回类型均相同。
重写方法不能拥有比父类更低的访问修饰符,可以拥有与父类方法相同或更宽松的异常抛出声明。
重载和重写都是多态的一种表现形式,通过编译器和虚拟机的不同处理方式来实现。
4. 请解释Java中的final关键字的作用。
Java多态性及其应用研究

摘
要 :在 Jv aa面 向对 象的程序 设 计 中有 效地利 用 多 态性, 以提 高程序 的可扩 充性 、 灵活 性和程 序代 码 的 重用 可
率 。 就 Jv a a语 言 支 持 的 多 态 性 作 了 全 面 的 探 讨 ,旨在 希 望 Jv aa程 序 设 计 人 员 能 更 好 地 利 用 多 态 性 , 发 高效 、 开 灵 活 、 壮 的Jv 健 a a程 序 。
2 J v 语 言 的 多态 形 式研 究 aa
21 强 制 多 态 .
强制 多态 隐式 的将参 数按 某种方 法 . 转换 成 编译 器认 为正 确的类 型 以避免错误 。例如 , “ . 在 1 0+1 ” “ . . 、1 0 0+1 及 “. ” 1 0+ ” 1’个表 达式 中 ,第 1 表 达式 将 两个 du l的操作 数 相加 ; … 3 个 o be Jv 中特 别声 明 了这种 用 法 。第2 aa 个表 达 式 将d u l型 和it o be n相
重载 ( vr a ) 态是 让类 以统一 的方 式处 理不 同类 型数 O el d 多 o 据 的一 种手 段 。Jv 的方 法 重载 , 是 在类 中可 以创建 多 个方 aa 就 法, 它们 具有 相 同的名 字 , 但具 有不 同 的参数 和不 同的定 义 。 调 用方 法 时通 过 传递 给 它们 的不 同个 数 和类 型 的参 数来 决定 具 体使 用哪个 方法 。下 面是 一个 方法 重载 的例子 : 实例22T s v r a .v . et el d a a O o j p bi casT s v r a { u l l et el d c s O o
定 的 和 通 用 的4 类 : 制 的 、 载 的 、 数 的 和 包 含 的 。 制 多 小 强 重 参 强
Java多态_继承_覆盖_重载示例

Java多态、继承、覆盖、重载示例class A{public String f(D obj){return ("A and D");}public String f(A obj){return ("A and A");}}class B extends A{public String f(B obj){return ("B and B");}public String f(A obj){return ("B and A");}}class C extends B{}class D extends B{}public class testJava{public static void main(String[] args){A a1 = new A();A a2 = new B();B b = new B();C c = new C();D d = new D();System.out.println(a1.f(a1)); //返回结果A and ASystem.out.println(a1.f(b)); //返回结果A and ASystem.out.println(a1.f(c)); //返回结果A and ASystem.out.println(a1.f(d)); //返回结果A and DSystem.out.println(a2.f(a1)); //B and A 多态的重写,父类只能看到子类的同名方法 System.out.println(a2.f(b)); // B and ASystem.out.println(a2.f(c)); // B and ASystem.out.println(a2.f(d)); // A and DSystem.out.println(b.f(a1)); //子类的继承和重写B and ASystem.out.println(b.f(b)); // B and BSystem.out.println(b.f(c)); // B and BSystem.out.println(b.f(d)); // A and D}}返回的结果:A and AA and DA and AA and AB and AB and AB and AA and DB and AB and BB and BA and D多态解释:A a2=new B(); 这样的话,a2被转化为A类型。
列举java中多态的体现

列举java中多态的体现多态是面向对象编程中的一个重要概念,它允许不同的对象对同一消息做出不同的响应。
在Java中,多态性是通过继承和接口实现来实现的。
下面将列举Java中多态的体现。
一、方法重载方法重载是指在同一个类中定义了两个或两个以上名称相同但参数类型或个数不同的方法。
这种情况下,当调用该方法时,编译器会根据参数类型和个数来判断应该调用哪个方法。
这种方式就是Java中最基本的多态性体现。
二、方法覆盖方法覆盖是指子类重新定义了父类中已有的方法,并且子类和父类中该方法具有相同的名称、返回值类型和参数列表。
当使用父类引用变量引用子类对象时,调用该方法时会自动调用子类中定义的那个方法,而不是父类中定义的那个方法。
三、向上转型向上转型是指将子类对象赋值给父类引用变量。
这种情况下,可以通过父类引用变量来访问子类对象中继承自父类的成员变量和成员方法。
由于向上转型后只能访问到父类中定义的成员变量和成员方法,因此无法直接访问子类中定义的成员变量和成员方法。
四、动态绑定动态绑定是指在运行时根据对象的实际类型来确定调用哪个方法。
在Java中,所有的非私有方法都是动态绑定的,也就是说,当调用一个非私有方法时,编译器不会确定要调用哪个方法,而是等到运行时才根据对象的实际类型来确定要调用哪个方法。
五、抽象类和接口抽象类和接口也是Java中多态性的体现。
抽象类和接口都定义了一些规范,而具体实现则由子类来完成。
当使用父类引用变量引用子类对象时,可以通过父类引用变量来访问子类对象中实现了父类或接口中定义的规范的成员变量和成员方法。
六、多态数组多态数组是指数组中存储的元素可以是不同类型的对象。
在Java中,可以使用Object类型来定义一个多态数组,在运行时将不同类型的对象存储到该数组中。
由于Object类型是所有类型的父类,因此可以使用父类引用变量来访问存储在数组中的不同类型的对象。
七、泛型泛型也是Java中多态性的一种体现方式。
多态和重载的底层实现原理

多态和重载的底层实现原理多态和重载是面向对象编程中常用的两种技术,它们的底层实现原理是非常重要的。
在本文中,我们将深入探讨多态和重载的底层实现原理。
多态的底层实现原理多态是指同一个方法在不同的对象上具有不同的行为。
在Java中,多态是通过继承和接口实现的。
当一个子类继承了一个父类或者实现了一个接口时,它可以重写父类或接口中的方法,从而实现多态。
在Java中,多态的底层实现原理是通过虚拟方法表(VMT)和虚拟函数(Virtual Function)实现的。
每个对象都有一个指向它所属类的VMT指针,VMT中存储了该类的所有虚拟函数的地址。
当调用一个虚拟函数时,实际上是通过对象的VMT指针找到该函数的地址,然后调用该函数。
例如,假设有一个Animal类和一个Dog类,Dog类继承自Animal 类,并重写了Animal类中的eat()方法。
当我们创建一个Dog对象并调用它的eat()方法时,实际上是通过Dog对象的VMT指针找到Dog类中重写的eat()方法的地址,然后调用该方法。
重载是指在同一个类中定义多个同名的方法,但它们的参数列表不同。
在Java中,重载是通过方法签名实现的。
方法签名包括方法名和参数列表,但不包括返回类型。
在Java中,重载的底层实现原理是通过方法的参数列表和返回类型来区分不同的方法。
当我们调用一个重载的方法时,编译器会根据方法的参数列表和返回类型来确定调用哪个方法。
例如,假设有一个add()方法,它有两个重载版本:一个接受两个整数作为参数,另一个接受两个浮点数作为参数。
当我们调用add(1, 2)时,编译器会选择接受两个整数作为参数的add()方法;当我们调用add(1.0, 2.0)时,编译器会选择接受两个浮点数作为参数的add()方法。
总结多态和重载是面向对象编程中常用的两种技术,它们的底层实现原理是非常重要的。
多态是通过虚拟方法表和虚拟函数实现的,而重载是通过方法的参数列表和返回类型来区分不同的方法。
java多态的心得体会

java多态的心得体会Java多态是面向对象编程中的重要概念,通过使用多态,可以使代码更加灵活、可扩展和可维护。
在我使用Java进行开发过程中,对多态有了一些深入理解和体会。
下面是我关于Java多态的心得体会:一、多态的基本理解多态是指通过父类的引用变量来调用属于子类的对象方法,即通过父类接口来操作子类对象。
这样做的好处是,我们可以在不改变原有代码的情况下,通过替换不同的子类对象,实现不同的行为。
二、多态的实现方式在Java中实现多态有两种方式:继承和接口。
继承方式是通过继承父类来扩展子类,子类可以重写父类的方法,并进行不同的实现。
而接口方式是通过实现接口来定义不同的行为和规范,一个类可以实现多个接口。
三、多态的优势1. 代码的灵活性。
通过多态,我们可以在不改变原有代码的情况下,通过替换不同的子类对象,实现不同的行为。
这样可以减少重复的代码和冗余的逻辑,提高代码的重用性。
2. 代码的可扩展性。
当系统需要新增一个功能或者修改一个功能时,通过新增一个子类或者重写子类的方法,而不需要修改原有的代码。
这样可以减少对原有代码的侵入性,使得系统更加易于扩展和维护。
3. 代码的可维护性。
通过多态,系统的不同模块可以相对独立地进行开发和维护。
由于子类可以被替换,我们只需要关心父类的接口和规范,而不需要了解子类的具体实现细节。
这样可以降低系统的耦合性,使得代码更易于维护和修改。
4. 提高代码的可读性。
通过多态,代码的逻辑更加清晰明了。
我们可以通过父类的引用变量来调用子类的方法,而无需了解具体的子类类型。
这样可以使代码更加简洁、易读和易理解。
四、多态的使用注意事项1. 父类引用变量不能访问子类新增的方法。
在多态的情况下,父类引用变量只能访问父类共有的方法和属性。
如果子类新增了方法,那么在使用多态时,是无法通过父类引用变量来调用该方法的。
2. 父类引用变量可以强制转换为子类对象。
在多态的情况下,父类引用变量可以强制转换为子类对象,以便直接访问子类中定义的方法和属性。
java多态练习题

Java多态练习题一、选择题A. 多态是指同一方法可以根据对象的不同而有不同的实现B. 多态只能用于类的继承关系中C. 在Java中,方法重载不属于多态D. 多态可以提高代码的可扩展性和可维护性A. extendsB. implementsC. staticD. overrideA. 可以直接调用子类的特有方法B. 必须进行类型转换才能调用子类的特有方法C. 可以调用父类的所有方法D. 无法调用任何方法二、填空题1. 在Java中,多态的三个必要条件是:________、________和________。
2. 当子类重写父类的方法后,可以使用________关键字来调用父类的方法。
3. 在Java中,________关键字用于判断两个对象的类型是否相同。
三、判断题1. 多态允许同一操作作用于不同的对象,产生不同的执行结果。
()2. 方法重载(Overload)和方法重写(Override)都是实现多态的方式。
()3. 在Java中,子类对象可以直接赋值给父类引用,而无需进行类型转换。
()四、简答题1. 请简述Java中多态的作用。
2. 请说明方法重写(Override)和方法重载(Overload)的区别。
3. 在使用多态时,如何访问子类特有的方法?五、编程题1. 定义一个动物类(Animal),包含一个吃(eat)的方法。
再定义一个狗类(Dog),继承动物类,并重写吃(eat)方法。
编写一个测试类,创建一个动物类引用,指向一个狗对象,并调用吃(eat)方法。
2. 编写一个图形类(Shape),包含一个求面积(getArea)的方法。
再定义两个子类:矩形类(Rectangle)和圆形类(Circle),分别重写求面积(getArea)方法。
编写一个测试类,创建一个图形数组,包含矩形和圆形对象,遍历数组并调用求面积(getArea)方法。
3. 定义一个员工类(Employee),包含姓名、工资等属性,以及一个计算工资(calculateSalary)的方法。
多态的实现原理

多态的实现原理多态是面向对象编程语言的一种重要特性,其可以使得程序在运行时动态地选择调用哪个具体方法,从而增加代码的灵活性和可维护性。
在Java等编程语言中,多态主要是通过接口和继承实现的。
本文将介绍多态的实现原理及其基本概念。
1. 多态的基本概念多态是指同一对象在不同情形下的多种表现形态。
更具体地说,多态有两种形式:编译时多态(静态多态)和运行时多态(动态多态)。
编译时多态是指在编译阶段就能确定所调用的方法,也称为静态多态。
其主要实现方式是方法重载,即在同一个类中定义多个同名的方法,但它们的方法参数类型、数量或顺序不同。
编译器会根据传入参数的不同自动选择具体的方法。
运行时多态是指程序在运行阶段才能根据具体情况动态地选择调用哪个方法,也称为动态多态。
其主要实现方式是方法覆盖,即在子类中重新定义与父类中相同的方法名称和参数列表。
这样,在运行时,调用子类对象的方法时,编译器会首先在子类中查找该方法,如果找到,则直接调用子类中的方法;如果没有找到,则会去父类中查找该方法。
这种机制也称为“虚方法调用”。
2. 多态的实现方式在Java等编程语言中,多态主要是通过继承和接口实现的。
继承是指一个类从另一个类继承属性和方法,并且可以重写方法。
接口是指一组方法声明,而没有方法体,子类可以实现这些方法。
在下面的例子中,我们借助Java语言来说明实现多态的两种方式。
首先,我们定义一个抽象类和一个实现这个抽象类的子类:javaabstract class Animal {public abstract void say();}class Cat extends Animal {public void say() {System.out.println("I'm a cat.");}}抽象类Animal定义了一个抽象方法say(),而Cat类继承了Animal类,并重写了say()方法。
接下来,我们创建一个方法,该方法接收一个Animal类型的参数,并调用该参数的say()方法:javapublic static void makeSound(Animal animal) {animal.say();}在调用makeSound方法时,我们可以传递一个Animal类型的对象或一个Cat 类型的对象,代码如下:javapublic static void main(String[] args) {Animal animal = new Cat();makeSound(animal); 输出:I'm a cat.}因为Cat类继承了Animal类并重写了say()方法,在调用makeSound方法时,我们将Cat类型的对象传递给animal参数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性。
在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度;今天我们再次深入Java核心,一起学习Java中多态性的实现。
“polymorphism(多态)”一词来自希腊语,意为“多种形式”。
多数Java程序员把多态看作对象的一种能力,使其能调用正确的方法版本。
尽管如此,这种面向实现的观点导致了多态的神奇功能,胜于仅仅把多态看成纯粹的概念。
Java中的多态总是子类型的多态。
几乎是机械式产生了一些多态的行为,使我们不去考虑其中涉及的类型问题。
本文研究了一种面向类型的对象观点,分析了如何将对象能够表现的行为和对象即将表现的行为分离开来。
抛开Java中的多态都是来自继承的概念,我们仍然可以感到,Java中的接口是一组没有公共代码的对象共享实现。
多态的分类多态在面向对象语言中是个很普遍的概念.虽然我们经常把多态混为一谈,但实际上有四种不同类型的多态。
在开始正式的子类型多态的细节讨论前,然我们先来看看普通面向对象中的多态。
Luca Cardelli和Peter Wegner("On Understanding Types, Data Abstraction, and Polymorphism"一文的作者,文章参考资源链接)把多态分为两大类----特定的和通用的----四小类:强制的,重载的,参数的和包含的。
他们的结构如下:在这样一个体系中,多态表现出多种形式的能力。
通用多态引用有相同结构类型的大量对象,他们有着共同的特征。
特定的多态涉及的是小部分没有相同特征的对象。
四种多态可做以下描述:◆强制的:一种隐式做类型转换的方法。
◆重载的:将一个标志符用作多个意义。
◆参数的:为不同类型的参数提供相同的操作。
◆包含的:类包含关系的抽象操作。
我将在讲述子类型多态前简单介绍一下这几种多态。
强制的多态强制多态隐式的将参数按某种方法,转换成编译器认为正确的类型以避免错误。
在以下的表达式中,编译器必须决定二元运算符‘+’所应做的工作:2.0 + 2.02.0 + 22.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类的所有参数。
1. C c = new C();2.3.Derived derived = new Derived();4.5. c.m( derived );并且,隐式的强制转换,可以避免类型转换的麻烦,减少编译错误。
当然,编译器仍然会优先验证符合定义的对象类型。
重载的多态重载允许用相同的运算符或方法,去表示截然不同的意义。
‘+’在上面的程序中有两个意思:两个double型的数相加;两个串相连。
另外还有整型相加,长整型,等等。
这些运算符的重载,依赖于编译器根据上下文做出的选择。
以往的编译器会把操作数隐式转换为完全符合操作符的类型。
虽然Java明确支持重载,但不支持用户定义的操作符重载。
Java支持用户定义的函数重载。
一个类中可以有相同名字的方法,这些方法可以有不同的意义。
这些重载的方法中,必须满足参数数目不同,相同位置上的参数类型不同。
这些不同可以帮助编译器区分不同版本的方法。
编译器以这种唯一表示的特征来表示不同的方法,比用名字表示更为有效。
据此,所有的多态行为都能编译通过。
强制和重载的多态都被分类为特定的多态,因为这些多态都是在特定的意义上的。
这些被划入多态的特性给程序员带来了很大的方便。
强制多态排除了麻烦的类型和编译错误。
重载多态像一块糖,允许程序员用相同的名字表示不同的方法,很方便。
参数的多态参数多态允许把许多类型抽象成单一的表示。
例如,List 抽象类中,描述了一组具有同样特征的对象,提供了一个通用的模板。
你可以通过指定一种类型以重用这个抽象类。
这些参数可以是任何用户定义的类型,大量的用户可以使用这个抽象类,因此参数多态毫无疑问的成为最强大的多态。
乍一看,上面抽象类好像是java.util.List的功能。
然而,Java实际上并不支持真正的安全类型风格的参数多态,这也是java.util.List和java.util的其他集合类是用原始的 ng.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的UML类图给出了类和类型的简单继承关系,以便于解释多态机制。
模型中包含5种类型,4个类和一个接口。
虽然UML中称为类图,我把它看成类型图。
如"Thanks Type and Gentle Class," 一文中所述,每个类和接口都是一种用户定义的类型。
按独立实现的观点(如面向类型的观点),下图中的每个矩形代表一种类型。
从实现方法看,四种类型运用了类的结构,一种运用了接口的结构。
图1:示范代码的UML类图以下的代码实现了每个用户定义的数据类型,我把实现写得很简单。
用这样的类型声明和类的定义,图2从概念的观点描述了Java指令。
Derived2 derived2 = new Derived2();图2 :Derived2 对象上的引用上文中声明了 derived2这个对象,它是Derived2类的。
图2种的最顶层把Derived2引用描述成一个集合的窗口,虽然其下的Derived2对象是可见的。
这里为每个Derived2类型的操作留了一个孔。
Derived2对象的每个操作都去映射适当的代码,按照上面的代码所描述的那样。
例如,Derived2对象映射了在Derived中定义的m1()方法。
而且还重载了Base类的m1()方法。
一个Derived2的引用变量无权访问 Base类中被重载的m1()方法。
但这并不意味着不可以用super.m1()的方法调用去使用这个方法。
关系到derived2这个引用的变量,这个代码是不合适的。
Derived2的其他的操作映射同样表明了每种类型操作的代码执行。
既然你有一个Derived2对象,可以用任何一个Derived2类型的变量去引用它。
如图1所示,Derived, Base和IType都是Derived2的基类。
所以,Base类的引用是很有用的。
图3描述了以下语句的概念观点。
Base base = derived2;图3:Base类引用附于Derived2对象之上虽然Base类的引用不用再访问m3()和m4(),但是却不会改变它Derived2对象的任何特征及操作映射。
无论是变量derived2还是 base,其调用m1()或m2(String)所执行的代码都是一样的。
两个引用之所以调用同一个行为,是因为Derived2对象并不知道去调用哪个方法。
对象只知道什么时候调用,它随着继承实现的顺序去执行。
这样的顺序决定了Derived2对象调用Derived里的m1()方法,并调用Derived2 里的m2(String)方法。
这种结果取决于对象本身的类型,而不是引用的类型。
尽管如此,但不意味着你用derived2和 base引用的效果是完全一样的。
如图3所示,Base的引用只能看到Base类型拥有的操作。
所以,虽然Derived2有对方法m3()和m4()的映射,但是变量base不能访问这些方法。
运行期的Derived2对象保持了接受m3()和m4()方法的能力。
类型的限制使 Base 的引用不能在编译期调用这些方法。
编译期的类型检查像一套铠甲,保证了运行期对象只能和正确的操作进行相互作用。
换句话说,类型定义了对象间相互作用的边界。
多态的依附性类型的一致性是多态的核心。
对象上的每一个引用,静态的类型检查器都要确认这样的依附和其对象的层次是一致的。
当一个引用成功的依附于另一个不同的对象时,有趣的多态现象就产生了。
(严格的说,对象类型是指类的定义。
)你也可以把几个不同的引用依附于同一个对象。
在开始更有趣的场景前,我们先来看一下下面的情况为什么不会产生多态。
多个引用依附于一个对象图2和图3描述的例子是把两个及两个以上的引用依附于一个对象。
虽然Derived2对象在被依附之后仍保持了变量的类型,但是,图3中的Base类型的引用依附之后,其功能减少了。
结论很明显:把一个基类的引用依附于派生类的对象之上会减少其能力。
一个开发这怎么会选择减少对象能力的方案呢?这种选择是间接的。
假设有一个名为ref的引用依附于一个包含如下方法的类的对象:用一个Derived2的参数调用poly(Base)是符合参数类型检查的:方法调用把一个本地Base类型的变量依附在一个引入的对象上。
所以,虽然这个方法只接受Base类型的参数,但Derived2对象仍是允许的。
开发这就不必选择丢失功能的方案。
从人眼在通过Derived2对象时所看到的情况,Base 类型引用的依附导致了功能的丧失。
但从执行的观点看,每一个传入poly1(Base)的参数都认为是Base的对象。