Java面向对象(五)

打印 上一主题 下一主题

主题 923|帖子 923|积分 2769

Java面向对象(五)


目录

十六、面向对象特征之三: 多态性

16.1 多态性的定义:


  • 对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)。
    可以直接应用在抽象类和接口上
  • Java 引用变量有两个类型:编译时类型和运行时类型。
    编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定
    简称:编译时,看左边;运行时,看右边。
  • 若编译时类型和运行时类型不一致,就出现了对象的多态性。
  1. public class Person {
  2.         ......
  3. }
  4. public class Man extends Person{
  5.         ......
  6. }
  7. public class Weman extends Person{
  8.         ......
  9. }
  10. public class PersonTest {
  11.        
  12.         public static void main(String[] args) {
  13.                
  14.                 Person p1 = new Person();
  15.                 Man man = new Man();
  16.                
  17.                 //对象的多态性:父类的引用指向子类的对象
  18.         //编译时声明了一个Person类型的变量p2,运行时实际引用的是Man类型的实例对象
  19.         //所以,当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
  20.                 Person p2 = new Man();
  21.                 Person p3 = new Woman();
  22.                
  23.         }
  24. }
复制代码
16.2 多态性的使用:


  • 虚拟方法调用(Virtual Method Invocation):

    • 正常方法调用:
      1. Person e = new Person();
      2. e.getInfo();
      3. Student e = new Student();
      4. e.getInfo();
      复制代码
    • 虚拟方法调用(多态情况下):
      子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
      1. Person e = new Student();
      2. e.getInfo(); //调用Student类的getInfo()方法
      3. /*
      4. 编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。——动态绑定
      5. */
      复制代码

  • 多态性的使用前提:① 类的继承关系  ② 方法的重写
  • 对象的多态性,只适用于方法,不适用于属性(属性值编译和运行都看左边)。
  • 多态性使用举例:
    1. import java.sql.Connection;
    2. //多态性的使用举例一:
    3. public class AnimalTest {
    4.        
    5.         public static void main(String[] args) {
    6.                
    7.                 AnimalTest test = new AnimalTest();
    8.                 test.func(new Dog());                //输出:狗进食 狗叫
    9.                
    10.                 test.func(new Cat());                //输出:猫进食 猫叫
    11.         }
    12.        
    13.         public void func(Animal animal){        //Animal animal = new Dog();
    14.                 animal.eat();
    15.                 animal.shout();
    16.         }
    17. }
    18. class Animal{
    19.        
    20.         public void eat(){
    21.                 System.out.println("动物:进食");
    22.         }
    23.        
    24.         public void shout(){
    25.                 System.out.println("动物:叫");
    26.         }
    27.        
    28.        
    29. }
    30. class Dog extends Animal{
    31.         public void eat(){
    32.                 System.out.println("狗进食");
    33.         }
    34.        
    35.         public void shout(){
    36.                 System.out.println("狗叫");
    37.         }
    38.        
    39.         public void watchDoor(){
    40.                 System.out.println("狗看门");
    41.         }
    42. }
    43. class Cat extends Animal{
    44.         public void eat(){
    45.                 System.out.println("猫进食");
    46.         }
    47.        
    48.         public void shout(){
    49.                 System.out.println("猫叫");
    50.         }
    51. }
    52. //举例二:
    53. class Order{
    54.        
    55.         public void method(Object obj){
    56.                
    57.         }
    58. }
    59. //举例三:数据库连接
    60. class Driver{
    61.        
    62.         public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
    63.                 //规范的步骤去操作数据
    64. //                conn.method1();
    65. //                conn.method2();
    66. //                conn.method3();
    67.                
    68.         }
    69. }
    复制代码
16.3 多态典型例题
  1. public class InterviewTest1 {
  2.     public static void main(String[] args) {
  3.         Base1 base = new Sub1();
  4.         base.add(1, 2, 3);                        //输出:sub_1
  5.         Sub1 s = (Sub1)base;
  6.         s.add(1,2,3);                                //输出:sub_2
  7.     }
  8. }
  9. class Base1 {
  10.     public void add(int a, int... arr) {
  11.         System.out.println("base1");
  12.     }
  13. }
  14. class Sub1 extends Base1 {
  15.     public void add(int a, int[] arr) {
  16.         System.out.println("sub_1");
  17.     }
  18.     public void add(int a, int b, int c) {
  19.         System.out.println("sub_2");
  20.     }
  21. }
  22. //        public void add(int a, int... arr) 和 public void add(int a, int[] arr) 是方法重写。
复制代码
十七、instanceof 关键字

17.1 instanceof 的引入:


  • 有了对象的多态性以后,该对象实例在内存中不仅加载了父类的属性和方法,实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。
  • 如何才能调用子类特有的属性和方法?
    向下转型:使用强制类型转换符。
  1. Person p2 = new Man();
  2. //p2变量声明为 Person 类型,不能调用子类 Man 类特有的方法
  3. //p2.earnMoney();
  4. //p2.isSmoking = true;
  5. //向下转型
  6. Man m1 = (Man)p;
  7. m1.earnMoney();
  8. m1.isSmoking = true;
  9. //使用强转时,可能出现ClassCastException的异常。
  10. //                Woman w1 = (Woman)p2;        编译通过,运行报错。
  11. //                p2变量是一个Person类型的变量,但定义时new的是Man型,实际上指向Man型的对象
  12. //                w1.goShopping();
复制代码

  • 为了避免在向下转型时出现 ClassCastException 的异常,我们在向下转型之前,先进行 instanceof 的判断,一旦返回 true,就进行向下转型。如果返回 false,不进行向下转型。
  1.                 //问题一:编译时通过,运行时不通过
  2.                 //举例一:
  3. //                Person p3 = new Woman();
  4. //                Man m3 = (Man)p3;
  5.                 //举例二:
  6. //                Person p4 = new Person();
  7. //                Man m4 = (Man)p4;
  8.                
  9.                 //问题二:编译通过,运行时也通过
  10. //                Object obj = new Woman();
  11. //                Person p = (Person)obj;
  12.                
  13.                 //问题三:编译不通过
  14. //                Man m5 = new Woman();
  15.                
  16. //                String str = new Date();
  17.                
  18. //        总结:可以这么理解,子类在创建时会加载所有的父类,转型也只能在已加载的类之间相互转型。
  19. //        否则,就算是编译不报错,运行也会报错!
复制代码
17.2 instanceof 的使用:


  • a instanceof A:判断对象a是否是类A的实例。如果是,返回 true;如果不是,返回 false。
  • 当类B是类A的父类。
    如果 a instanceof A 返回 true,则 a instanceof B 也返回 true。
  1. public class Person extends Object {…}
  2. public class Student extends Person {…}
  3. public class Graduate extends Person {…}
  4. public void method1(Person e) {
  5.        if (e instanceof Person)
  6. // 处理Person类及其子类对象
  7.        if (e instanceof Student)
  8. //处理Student类及其子类对象
  9.        if (e instanceof Graduate)
  10. //处理Graduate类及其子类对象
  11. }
复制代码
17.3 向下转型和向上转型拓展


  • 从子类到父类的类型转换可以自动进行。
  • 从父类到子类的类型转换必须通过造型(强制类型转换)实现。
  • 无继承关系的引用类型间的转换是非法的。(类型转换异常)

十八、Object 类的使用

18.1 Object 类介绍


  • Object 类是所有 Java 类的根父类。
  • 如果在类的声明中未使用 extends 关键字指明其父类,则默认父类为 java.lang.Object 类。
  • Object 类中的功能(属性、方法)就具有通用性。
​                属性:无
​                方法:equals(),toString() ,getClass(),hashCode(),clone(),finalize(),wait(),notify(),notifyAll()。

  • Object 类只声明了一个空参的构造器。
18.2 == 与 equals() 方法

18.2.1  == 运算符


  • 可以使用在基本数据类型变量和引用数据类型变量中。
  • 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
    1. public class EqualsTest {
    2.     public static void main(String[] args) {
    3.         //基本数据类型
    4.         int i = 10;
    5.         int j = 10;
    6.         double d = 10.0;
    7.         System.out.println(i == j);//true
    8.         System.out.println(i == d);//true
    9.                
    10.         char c = 10;
    11.                 System.out.println(i == c);//true
    12.                
    13.                 char c1 = 'A';
    14.                 char c2 = 65;
    15.                 System.out.println(c1 == c2);//true
    16.     }
    17. }
    复制代码
​       如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体。
补充: == 符号使用时,必须保证符号左右两边的变量类型一致。
18.2.2  equals() 方法的使用
  1. 1. 是一个方法,而非运算符。
  2. 2. 只能适用于引用数据类型。
  3. 3. Object类中equals()的定义:
复制代码
  1. public boolean equals(Object obj) {
  2.         return (this == obj);
  3. }
复制代码
说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体。

  • 像 String、Date、File、包装类等都重写了 Object 类中的 equals() 方法。
    重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同
  1. public class EqualsTest {
  2.     public static void main(String[] args) {
  3.      //引用类型:
  4.                 Customer cust1 = new Customer("Tom",21);
  5.                 Customer cust2 = new Customer("Tom",21);
  6.                 System.out.println(cust1 == cust2);//false
  7.                
  8.                 String str1 = new String("xiaozhao");
  9.                 String str2 = new String("xiaozhao");
  10.                 System.out.println(str1 == str2);                        //false
  11.                
  12.                 System.out.println(cust1.equals(cust2));        //false(调用Object类中的equals()方法)
  13.                 System.out.println(str1.equals(str2));                //true
  14.                
  15.                 Date date1 = new Date(32432525324L);
  16.                 Date date2 = new Date(32432525324L);
  17.                 System.out.println(date1.equals(date2));        //true
  18.     }
  19. }
  20. public class Customer {
  21.     public String name;
  22.     public int age;
  23. }
复制代码
18.2.3 重写 equals() 方法


  • 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。
    那么,我们就需要对 Object 类中的 equals() 进行重写。
  • 重写的原则:比较两个对象的实体内容是否相同。
  • 一般情况下,使用 IDE 自动重写 equals() 方法。
18.3 toString() 方法


  • 当我们输出一个对象的引用时,实际上就是调用当前对象的 toString() 方法。
  • Object类中toString()的定义:
  1. public String toString() {
  2.    return getClass().getName() + "@" + Integer.toHexString(hashCode());
  3. }
复制代码

  • 像 String、Date、File、包装类等都重写了 Object 类中的 toString() 方法。使得在调用对象的 toString() 时,返回"实体内容"信息。
  • 自定义类也可以重写 toString() 方法,当调用此方法时,返回对象的"实体内容"。
    可以手动重写和自动重写,一般使用自动重写。
  1. public class ToStringTest {
  2.         public static void main(String[] args) {
  3.                
  4.                 Customer cust1 = new Customer("Tom",21);
  5.                 System.out.println(cust1.toString());        //javase.ex.Customer@1b6d3586
  6.                 System.out.println(cust1);                                //javase.ex.Customer@1b6d3586
  7.                
  8.                 String str = new String("xiaozhao");
  9.                 System.out.println(str);                                //xiaozhao
  10.                
  11.                 Date date = new Date(4534534534543L);
  12.                 System.out.println(date.toString());        //Mon Sep 11 08:55:34 CST 2113
  13.                
  14.         }
  15. }
  16. public class Customer {
  17.     public String name;
  18.     public int age;
  19.     public Customer(String name, int age) {
  20.         this.name = name;
  21.         this.age = age;
  22.     }
  23. /*自动重写的 toString 方法
  24.         @Override
  25.     public String toString() {
  26.         return "Customer{" +
  27.                 "name='" + name + '\'' +
  28.                 ", age=" + age +
  29.                 '}';
  30.     }
  31. */
  32. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

去皮卡多

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表