• Java面向对象编程(四)


    目录

    一、子类对象实例化过程

     1、从结果上来看(继承性)

    2、从过程上来看

    二、多态性

    多态性的使用前提

    多态的使用

    多态应用举例

    虚方法的调用

    正常方法调用

    虚方法的调用

    编译时类型和运行时类型

    对象类型转换(Casting)

    instanceof操作符

    instanceof练习

    多态练习


    一、子类对象实例化过程

     

     1、从结果上来看(继承性)

    •  子类继承父类以后就获取了父类中声明的属性和方法
    • 创建子类的对象时会在堆空间中加载所有父类中声明的属性

    2、从过程上来看

    • 当我们通过子类的构造器创建子类的对象时,一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,直到调用到java.lang.Object类中的空参的构造器上为止,正因为加载过了所有父类中的结构,所以才可以看到内存中有父类中声明的结构,子类中的对象才可以考虑进行调用

            注意:虽然创建子类对象时调用了父类的构造器,但自始至终只创建了一个子类对象,即为new的子类对象

    二、多态性

    多态性是面向对象的重要概念。多态性在java中的体现为:父类的引用指向子类的对象(向上转型 upcasting)

    多态性的使用前提

    1、要有类的继承关系

    2、要有方法的重写

    多态的使用

    java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型有由际赋给该变量的对象决定。当编译时类型和运行时类型不一致时,就出现了多态性。

    有了对象的多态性以后,在编译期,只能调用父类中声明的方法,但在运行期,实际执行的是子类重写父类的方法。(虚拟方法的调用)

    注意:对象的多态性,只适用于方法,不适用于属性

    如果一个引用类型变量声明为父类的类型,但实际引用的是子类的对象,那么该变量就不能再访问子类中添加的属性和方法。即有了对象的多态性后,在内存中实际上是加载了子类的属性和方法的,但是由于变量声明的是父类类型,导致编译时只能调用父类中声明的方法和属性,子类特有的属性和方法不能调用。

    多态应用举例

    方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法

    1. public class Test {
    2. public void method(Person e) {
    3. // ……
    4. e.getInfo();
    5. }
    6. public static void main(Stirng args[]) {
    7. Test t = new Test();
    8. Student m = new Student();
    9. t.method(m); // 子类的对象m传送给父类类型的参数e
    10. }
    11. }

    虚方法的调用

    正常方法调用

    Person e =new Person();

    e.getInfo();

    Student s=new Student();

    s.getIfo();

    虚方法的调用

    子类中定义了与父类中同名同参数的方法,在多态的情况下 ,将此时的父类的方法称为虚拟方法。父类根据付给他的不同的子类对象,动态地调用属于子类的方法。这样的方法调用在编译期是无法确定的。

    Person e =new Student();

    e.getInfo();

    编译时类型和运行时类型

    编译是e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法(动态绑定)

    因此,我们说多态是运行时行为。

    对象类型转换(Casting)

    如果想让子类对象可以使用自己类中的属性及方法时,就要对带对象进行强制类型转换,java对象的强制类型转换称为造型。

    说明:

    1、从子类到父类的类型可以进行自动转换

    2、从父类到子类的类型转换必须是通过(强制类型转换)实现

    3、无继承关系的引用类型间的转换是非法的

    4、在造型前可以使用instanceof操作符测试一个对象的类型

    instanceof操作符

    如果子类想继续使用为了避免在向下转型之前出项classCastExecption的异常,我们可以在向下转型之前,先进性instanceof判断,一旦返回true,就进行向下转型,如果返回false,则不进行向下转型。

    x instanceof A

    检验是否为类A的对象,返回值为boolean型

    要求x所属的类于类A必须是子类和父类的关系,否则编译报错(必须存在继承)

    如果x属于类A的子类B,x instanceof A 的值也为true

    instanceof练习

    建立InstanceTest 类,在类中定义方法 method(Person e);

    在method中:

    (1)根据e的类型调用相应类的getInfo()方法。

    (2)根据e的类型执行:

    如果e为Person类的对象,输出: “a person”;

    如果e为Student类的对象,输出: “a student” “a person ”

    如果e为Graduate类的对象,输出: “a graduated student” “a student” “a person”

    1. public class InstanceTest {
    2. public static void main(String[] args) {
    3. InstanceTest test =new InstanceTest();
    4. test.method(new Person());
    5. System.out.println("------------");
    6. test.method(new Student());
    7. System.out.println("------------");
    8. test.method(new Graduate());
    9. }
    10. public void method(Person e) {
    11. String info = e.getInfo();
    12. System.out.println(info);
    13. if(e instanceof Graduate) {
    14. System.out.println("a garduated student"+"\na student"+"\na person");
    15. }else if(e instanceof Student) {
    16. System.out.println("a student"+"\na person");
    17. }else {
    18. System.out.println("a person");
    19. }
    20. }
    21. }
    22. class Person{
    23. protected String name="person";
    24. protected int age=50;
    25. public String getInfo() {
    26. return "Name:"+name+"\n"+"age:"+age;
    27. }
    28. }
    29. class Student extends Person{
    30. protected String school="pku";
    31. public String getInfo() {
    32. return "Name:"+name+"\nage:"+age
    33. +"\nschool"+school;
    34. }
    35. }
    36. class Graduate extends Student{
    37. public String major="IT";
    38. public String getInfo() {
    39. return "Name:"+name+"\nage:"+age
    40. +"\nschool"+school+"\nmajor"+major;
    41. }
    42. }

    运行结果如下:

    多态练习

    定义三个类,父类GeometricObject代表几何形状,子类Circle代表圆形,MyRectangle代表矩形。 定义一个测试类GeometricTest,编写equalsArea方法测试两个对象的面积是否相等(注意方法的参 数类型,利用动态绑定技术),编写displayGeometricObject方法显示对象的面积(注意方法的参 数类型,利用动态绑定技术)。

     

    1. public class GeometricTest {
    2. public static void main(String[] args) {
    3. GeometricTest geo=new GeometricTest();
    4. //测试面积是否相等
    5. geo.equalArea(new Circle(2.5,"red",2.5),new Circle(2.6,"red",2.5));
    6. //分别显示圆和对象的面积
    7. geo.displayGeometricObject(new Circle(2.5,"red",2.5),new MyRectangle(2, 2, "blue", 2));
    8. }
    9. /**
    10. * 测试两个对象的面积是否相等 动态绑定
    11. */
    12. public void equalArea(GeometricObject cir,GeometricObject rec) {
    13. if(cir.findArea()==rec.findArea()) {
    14. System.out.println("两对象面积相等");
    15. }else {
    16. System.out.println("两对象面积不相等");
    17. }
    18. }
    19. /***
    20. * 显示对象面积 动态绑定
    21. */
    22. public void displayGeometricObject(GeometricObject cir,GeometricObject rec) {
    23. System.out.println("圆形的面积是:"+cir.findArea());
    24. System.out.println("矩形的面积是:"+rec.findArea());
    25. }
    26. }
    27. /**
    28. * 几何形状
    29. * @author light
    30. * 父类
    31. *
    32. */
    33. class GeometricObject{
    34. protected String color;
    35. protected double weight;
    36. protected GeometricObject(String color,double weight) {
    37. this.color=color;
    38. this.weight=weight;
    39. }
    40. public String getColor() {
    41. return color;
    42. }
    43. public void setColor(String color) {
    44. this.color = color;
    45. }
    46. public double getWeight() {
    47. return weight;
    48. }
    49. public void setWeight(double weight) {
    50. this.weight = weight;
    51. }
    52. public double findArea() {
    53. return 0.0;
    54. }
    55. }
    56. /**
    57. * 圆形
    58. * @author light
    59. * 继承于GeometricObject类
    60. *
    61. */
    62. class Circle extends GeometricObject{
    63. private double radius;
    64. public Circle(double radius,String color,double weight) {
    65. super(color, weight);
    66. this.radius=radius;
    67. }
    68. public double getRadius() {
    69. return radius;
    70. }
    71. public void setRadius(double radius) {
    72. this.radius = radius;
    73. }
    74. /**
    75. * @Override 圆形类重写父类返回面积方法
    76. */
    77. public double findArea() {
    78. return getRadius()*getRadius()*Math.PI;
    79. }
    80. }
    81. /**
    82. * 矩形
    83. * @author light
    84. * 继承于GeometricObject类
    85. *
    86. */
    87. class MyRectangle extends GeometricObject{
    88. private double width;
    89. private double height;
    90. public MyRectangle(double width,double height,String color,double weight) {
    91. super(color,weight);
    92. this.width=width;
    93. this.height=height;
    94. }
    95. public double getWidth() {
    96. return width;
    97. }
    98. public void setWidth(double width) {
    99. this.width = width;
    100. }
    101. public double getHeight() {
    102. return height;
    103. }
    104. public void setHeight(double height) {
    105. this.height = height;
    106. }
    107. /**
    108. * @Override 矩形类重写父类返回面积方法
    109. */
    110. public double findArea() {
    111. return getHeight()*getWidth();
    112. }
    113. }

    运行结果如下:

  • 相关阅读:
    Spirng Cloud Alibaba Nacos注册中心的使用 (环境隔离、服务分级存储模型、权重配置、临时实例与持久实例)
    JAVA入门——方法引用
    深度学习笔记: 最详尽解释预测系统的分类指标(精确率、召回率和 F1 值)
    JavaIO流: IO流原理即流的分类
    golang 和rabbitMq 这个代码写的也很好呀!
    20世纪最佳12部学术专著
    JVM实用参数(一)JVM类型以及编译器模式
    从零开始学习c++全套通关系列(第一章)万字总结,建议收藏~
    iOS开发app置灰功能添加
    MySQL数据库下载与安装使用
  • 原文地址:https://blog.csdn.net/zssxcj/article/details/127531829