参数类型对java用继承实现多态时的影响
2015-07-18 22:40
453 查看
最近对java父子类关系以及继承和多态有了新的理解。
java多态有两种形式,一种是通过方法重载实现的编译时多态,另一种是通过类之间的继承、方法重写以及晚联编技术实现的运行时多态。
对于被子类重写的、父类中的无参的方法不是本次讨论的对象,对于这个,因为是父类的引用指向了子类,当然是这次是关于类的继承以及父子类调用的一个test。调用了子类重写的方法,而父类中的原本的方法被隐藏了。
这次是关于方法含参且重写后父子类的方法参数不同的一个test。
下图是运行结果:
NO.1和NO.2实例化的就是父类和子类的对象,所以执行的就是该类本身的方法,没有实现多态。
NO.3中子类重写了父类的方法,调用的子类的方法,即实现了多态。
NO.4中,d是b的子类,而b又是a的子类,也就是d是a的子类的子类。由于b重写了a类方法,由NO.3可知,会调用b中的方法。可b中有参数为a的fun方法,也有参数为b的fun方法,究竟调用的是哪一个?从结果上看,它调用的是参数为b的方法,也就是将它匹配到了它亲爸那而不是它爷爷那......从这里也可以看出,两种类型有继承关系,即在继承树的同一个分支上时,java会自动进行类型转换的。
至于NO.5和NO.6,说明方法的执行并没有因为a、b是父子类而受到影响,总是绑定到关系最近、最精确的那一个。
NO.7中,类b中有参数为bb的方法,所以输出该结果。
而NO.8中,a类没有参数类型为bb的方法,所以道理同NO.4,执行了参数为bb父类的方法即参数为a的方法。
NO.9由于A1是指向了子类b的一个引用,但是并没有绑定参数类型为bb的fun()方法,这是因为指向子类的父类引用不能调用子类特有的方法(编译时会报错),而事实上这个参数类型为bb的方法也不是重写的父类方法,而是子类中的重载。
又看到一篇讨论静态变量和静态方法的绑定规则的文章,感觉不错,贴出来~
行时环境中,通过引用类型变量来访问所引用对象的方法和属性时,Java虚拟机采用以下绑定规则:
1, 实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机动态决定的 。
2, 静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经绑定 。
3, 成员变量(静态变量,实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经绑定 。
戳这儿 http://edison-cool911.iteye.com/blog/1131204
java多态有两种形式,一种是通过方法重载实现的编译时多态,另一种是通过类之间的继承、方法重写以及晚联编技术实现的运行时多态。
对于被子类重写的、父类中的无参的方法不是本次讨论的对象,对于这个,因为是父类的引用指向了子类,当然是这次是关于类的继承以及父子类调用的一个test。调用了子类重写的方法,而父类中的原本的方法被隐藏了。
这次是关于方法含参且重写后父子类的方法参数不同的一个test。
class a{ void fun(b B){ System.out.println("a and B"); } void fun(a A){ System.out.println("A and a"); } } class b extends a{ void fun(b B){ System.out.println("b and B"); } void fun(a A){ System.out.println("b and a"); } void fun(bb B){ System.out.println("a don't have this fun"); } } class bb extends a{ void fun(bb B){ System.out.println("a and bb"); } } class c{ void fun(a A ){ System.out.println("funa"); } void fun(b B){ System.out.println("funb"); } } class d extends b{ void fun(d D){ System.out.println("d and d"); } } public class Main{ public static void main(String[] args){ a A = new a(); b B = new b(); a A1 = new b(); c C = new c(); d D = new d(); A.fun(B);//NO.1 B.fun(B);//NO.2 A1.fun(B);//NO.3 A1.fun(D);//NO.4 C.fun(A);//NO.5 C.fun(B);//NO.6 bb BB = new bb(); B.fun(BB);//NO.7 A.fun(BB);//NO.8 A1.fun(BB);//NO.9 } }
下图是运行结果:
a and B //NO.1 b and B //NO.2 b and B //NO.3 b and B //NO.4 funa //NO.5 funb //NO.6 a don't have this fun //NO.7 A and a //NO.8 b and a //NO.9
NO.1和NO.2实例化的就是父类和子类的对象,所以执行的就是该类本身的方法,没有实现多态。
NO.3中子类重写了父类的方法,调用的子类的方法,即实现了多态。
NO.4中,d是b的子类,而b又是a的子类,也就是d是a的子类的子类。由于b重写了a类方法,由NO.3可知,会调用b中的方法。可b中有参数为a的fun方法,也有参数为b的fun方法,究竟调用的是哪一个?从结果上看,它调用的是参数为b的方法,也就是将它匹配到了它亲爸那而不是它爷爷那......从这里也可以看出,两种类型有继承关系,即在继承树的同一个分支上时,java会自动进行类型转换的。
至于NO.5和NO.6,说明方法的执行并没有因为a、b是父子类而受到影响,总是绑定到关系最近、最精确的那一个。
NO.7中,类b中有参数为bb的方法,所以输出该结果。
而NO.8中,a类没有参数类型为bb的方法,所以道理同NO.4,执行了参数为bb父类的方法即参数为a的方法。
NO.9由于A1是指向了子类b的一个引用,但是并没有绑定参数类型为bb的fun()方法,这是因为指向子类的父类引用不能调用子类特有的方法(编译时会报错),而事实上这个参数类型为bb的方法也不是重写的父类方法,而是子类中的重载。
又看到一篇讨论静态变量和静态方法的绑定规则的文章,感觉不错,贴出来~
行时环境中,通过引用类型变量来访问所引用对象的方法和属性时,Java虚拟机采用以下绑定规则:
1, 实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机动态决定的 。
2, 静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经绑定 。
3, 成员变量(静态变量,实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经绑定 。
戳这儿 http://edison-cool911.iteye.com/blog/1131204
相关文章推荐
- java学习笔记(二) InputStream
- Java学习之【深入理解Java虚拟机---Java内存区域】
- JDK的安装和Java环境变量配置
- Java 异常及异常处理
- Java学习笔记之<反射、内省、BeanUtils包操作JavaBean的对比>
- Spring实现AOP的4种方式
- spring jdbc rowmap 使用方法
- spring jdbc 事物的使用心得
- spring jdbc 使用感想
- java学习之旅63常用类_包装类_Integer_Number_JDK源码分析
- JAVA--反射(基础知识~~真的是基础的哦)
- JAVA基础_简析Java中的new,this,super,final关键字
- eclipse设置自动注释的@author的值 ${user}变量
- Java线程池使用说明
- Spring-01-HelloWorld
- java static关键字
- Java初涉之4--浅谈静态块和非静态块
- java中初始化对象变量的方法
- 使用缓冲流时记得恰当的使用flush()方法
- JAVA_SE基础——15.循环嵌套