1、定义:在程序中定义的某个引用变量具体所指向的类型和调用的方法在编码时并不能确定,而只有在运行的时候才能确定。
2、简单理解:你定义的引用变量是父类型,而你创建的对象是子类型,用这个父类型的引用变量指向这个子类型的对象,然后当你调用这个对象的方法的时候,具体是调用的父类的还是子类的方法只有在运行的时候才能确定,可能调用的是父类的方法也有可能调用的子类的方法,这样不用修改代码,就可以让成徐选择多个运行的状态,这就是多态。
3、要点:
1)多态的三大必要条件:继承、覆写、父类引用指向子类对象。
2)父类的实例方法可以被覆盖,属性不能被覆盖。
3)父类的引用可以访问父类的所有属性和方法,可以访问子类覆盖的方法(引用指向子类对象的话),但不能访问子类的属性(属性不能被覆盖),及子类新添加的方法。
4)父类引用会调用子类覆盖的方法即动态绑定,指定是程序在执行时(非编译期间)会判断引用对象的实际类型,并调用其相应的方法。
4、关于在集合中使用泛型及多态的问题
先看下以下代码能否通过编译?
实例一:
package com.linwei; import java.util.ArrayList; import java.util.List; abstract class Animal { public void eat(){ System.out.println("animal eating"); } } class Dog extends Animal{ public void bark(){ System.out.println("dog barking"); } } class Cat extends Animal{ public void meow(){ System.out.println("cat meowing"); } } public class TestDuotai { public void showAnimals(List<Animal> animals ){ //animals.add(new Cat()); for(Animal a : animals){ a.eat(); } } public static void main(String[] args) { ArrayList<Dog> dogs=new ArrayList<Dog>(); dogs.add(new Dog()); dogs.add(new Dog()); dogs.add(new Dog()); new TestDuotai().showAnimals(dogs); } }
答:不能编译通过。
问题出在该方法:showAnimals(List<Animal> animals )。该方法接受的是Animal类型的集合,按照多态的概念来说,Dog类是Animal类的子类,传入Dog类型的集合应该是没问题的,但为什么不能编译通过呢?
原因(反证法验证):
1)假设能够编译通过,则说明在一个需要List<Animal> 的地方可以传入ArrayList<Dog>对象,不过如果继续往方法的内部思考,就会存在问题。
2)见showAnimals(List<Animal> animals )方法内部的注释行://animals.add(new Cat()),假设把注释去掉,则由于Cat类也是Animal类的子类,所以该行代码也是完全没有问题的。
3)但回到方法的调用处:new TestDuotai().showAnimals(dogs),我们就会发现实际上我们传入showAnimals(List<Animal> animals )方法的是Dog类型的集合,但如果在方法中执行到animals.add(new Cat())代码时,意思是要往ArrayList<Dog>中传入一个Cat类型的对象,如此一来就涉及到了泛型安全性的问题,此时就不能通过编译器的编译(集合泛型类型的检查发生在编译期,而数组类型的检查则在运行期)。
4)结论:你不能向一个参数类型为ArrayList<Animal>的方法中传递ArrayList<Dog>类型的对象。
5) 关于以上第4)点的补充实例,代码如下所示。
package com.linwei; import java.util.ArrayList; import java.util.List; abstract class Animal { public void eat(){ System.out.println("animal eating"); } } class Dog extends Animal{ public void bark(){ System.out.println("dog barking"); } } class Cat extends Animal{ public void meow(){ System.out.println("cat meowing"); } } public class TestDuotai { public void showAnimals(List<Animal> animals ){ for(Animal a : animals){ a.eat(); } } public static void main(String[] args) { ArrayList<Dog> dogs1=new ArrayList<Animal>(); //不能编译通过 ArrayList<Animal> animals1=new ArrayList<Dog>(); //不能编译通过 List<Animal> list=new ArrayList<Animal>(); ArrayList<Dog> dogs=new ArrayList<Dog>(); ArrayList<Animal> animals = dogs; //不能编译通过 List<Dog> dogList=dogs; ArrayList<Object> objects=new ArrayList<Object>(); List<Object> objectList=objects; ArrayList<Object> objs=new ArrayList<Dog>(); //不能编译通过 } }
相关推荐
在阅读过程中,尝试编写简单的Java程序,体验多态的效果,并观察父类引用指向子类对象时的行为变化。 建议通过阅读相关的Java教材或搜索资料,进一步了解与多态相关的高级主题,如抽象类和接口等内容。 如有疑问,...
父类引用指向子类对象时,没法调用子类特有的方法; 父类引用指向子类对象: java中子类强转父类,实际上依然是子类; 该引用只能调用父类中定义的方法和变量; 如果子类中重写了父类中的一个方法,那么在...
黑马程序员 - Java基础教学 - 08 - 面向对象(4)-多态.doc
从子到父:父类引用指向子类的对象 父类 父类对象名 = new 子类(); 向下转型(强制类型转换) 从父到子:父类引用转为子类的对象 子类 子类对象名 = (子类)父类对象; 好处: 向上转型:父类引用指向子类对象,提高...
声明抽象类语法: abstract class{…… } 使用:父类中的某些抽象不包含任何逻辑,并需要在子类中重写,子类提供这种抽象方 法的实现细节 abstract 修饰符 3-2 抽象类可以具有指向子类对象的对象引用 abstract 修饰...
先来复习下java多态:java多态指的是父类引用指向子类对象,不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。 接下来我们再说下什么叫策略模式:将每一个算法封装到...
多态是面向对象编程中的一个重要特性,它允许一个类的引用变量指向多种实际类型。这意味着在运行时,可以调用不同的方法实现不同的功能 多态的实现方式 多态可以通过继承、接口和重写实现。子类继承父类后,可以使用...
最终多态体现为父类引用指向子类对象。 多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。 在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。 二、多态的定义与使用格式 ...
3.父类引用指向子类对 综合实际应用,我们做出以下总结: ① 成员变量 编译看左边(父类),运行看左边(父类) ② 成员方法 编译看左边(父类),运行看右边(子类)。动态绑定 ③ 静态方法 编译看左边(父类),运行看左边...
3、 父类引用指向子类对象 然后看一个例子 package test.xing; class Father{ protected int age; public Father(){ age = 40; } void eat(){ System.out.println(父亲在吃饭); } } class Child ...
运行时多态:重写,对象的多态性(父类的引用指向子类的实例) 5.CSDN 1.泛型的好处 保护类型安全 避免强制类性转化 2.final 1.修饰的属性是常量 2.修饰的方法不能被重写 3.修饰的类不能被继承 String
1.格式说明:父类引用指向子类对象。 具体什么意思呢? 变量有基本数据类型和引用数据类型。 其中引用数据类型又分为:数组,类和接口。 父类类型指的是子类继承至的父类,或者子类实现的接口。 按照现实里面的理解...
运用多态,将一个父类类型的变量指向子类类型的实例
父类引用指向子类对象 9.什么是方法重载?什么是方法重写?方法重载与方法重写的区别? 方法重载(Overload):是指方法名字相同,参数的个数、类型、次序不同。 方法重写(Override/Overwrite):是指子类重写了从父类...
25.3 父类的引用指向子类实例时,父类引用可以调用哪些方法? 35 26 引用类型的自动类型与强制类型转换 36 27 多态的应用 37 27.1 在使用多态时的一般格式: 37 27.2 练习:创建一个薪资专员(Persionnel),能计算...
//正确,可以指向子类对象 (4)由抽象类派生的子类必须实现所有父类的抽象方法,否则,该子类仍然是抽象类。 面向对象程序设计与实践-Java抽象类和接口[33页]全文共33页,当前为第8页。 抽象类 5-1关联知识 ...
•也就是说引用型变量里存放的仅仅是一个引用,它指向实际的对象. 对象的this 引用 •this 关键字总是指向调用该方法的对象. –1.构造器中引用该构造器执行初始化的对象 –2.在方法中引用调用该方法的...
所以,用父类的指针指向子类,是为了面向接口编程。大家都遵循这个接口,弄成一样的,到哪里都可以用。 3,提高程序的可复用性,提高可扩充行和可维护性,一个接口,多种实现,各自不同. 动态多态的基础知识:首先百度...
1. JAVA面向对象编程三大特征...多态:程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,在程序运行期间才确定。 两种方式:1.继承——多个子类对同一方法的重写;2.接口——实现
实际上是一个指针,此指针指向对象所占有的内存区域。 因此,对象名(变量)实际上存放的是一个被实例化之后的对象所占有的内存区域 的指针。 例如: type objectName = new type ( [paramlist] ); 运算符 new 为...