JavaEE 学习笔记 面向对象(中)12

第五章 面向对象(中)



Java 面向对象学习的三条主线:
        Java 类及类的成员:属性,方法,构造器,代码块,内部类
        面向对象的三大特征:封装性,继承性,多态性,(抽象性)
        其他关键字:this,super,static,final,abstract,interface,import等


       

5.5 面向对象特征之三:(多态性)

5.5.1 多态性的概述

        多态性,指一个事物的多种形态,是面向对象中最重要的概念,

        在Java中的体现:

                对象的多态性:父类的引用指向子类的对象

                        可以直接应用在抽象类和接口上

5.5.2 多态性的使用

        Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时变量由实际赋给该变量的对象决定,简称:编译时,看左边,运行时,看右边。

        若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)

        多态情况下,“看左边”:看的是父类的引用(父类中不具备子类持有的方法)

                             “看右边“:看的是子类的对象(实际运行的是子类重写父类的方法)

        对象的多态性只适应方法,不适应属性

5.5.3 多态性的使用前提

        ①.有类的继承        ②.有方法的重写 

5.5.4 虚拟方法调用(Virtual Method Invocation)

        正常的方法调用

                Person e= new Person();

                e.getInfo();

        虚拟方法调用(多态情况下)

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

                Person e= new Student();

                e.getInfo();        //调用Student类的getInfo()方法

        编译时类型和运行时类型

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

         运行时行为,证明见上

5.5.5 instanceof 操作符

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

        要求x所属的类与类A必须是子类和父类的关系,否则编译错误。

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


public class InstanceTest {
    public static void main(String[] args) {
        InstanceTest instanceTest = new InstanceTest();
        instanceTest.method(new Student());
    }

    public void method(Person e){
        String info = e.getInfo();
        System.out.println(info);

        if (e instanceof Graduate){
            System.out.println("a graduated student");
            System.out.println("a student");
            System.out.println("a person");
        }else if (e instanceof Student){
            System.out.println("a student");
            System.out.println("a person");
        }else {
            System.out.println("a person");
        }
    }
}

5.5.6 向下转型

5.5.7 多态性的使用实例


public class Test {
    public static void main(String[] args) {
      show(new Cat());  // 以 Cat 对象调用 show 方法
      show(new Dog());  // 以 Dog 对象调用 show 方法
                
      Animal a = new Cat();  // 向上转型  
      a.eat();               // 调用的是 Cat 的 eat
      Cat c = (Cat)a;        // 向下转型  
      c.work();        // 调用的是 Cat 的 work
  }  
            
    public static void show(Animal a)  {
      a.eat();  
        // 类型判断
        if (a instanceof Cat)  {  // 猫做的事情 
            Cat c = (Cat)a;  
            c.work();  
        } else if (a instanceof Dog) { // 狗做的事情 
            Dog c = (Dog)a;  
            c.work();  
        }  
    }  
}
 
abstract class Animal {  
    abstract void eat();  
}  
  
class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void work() {  
        System.out.println("抓老鼠");  
    }  
}  
  
class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
    public void work() {  
        System.out.println("看家");  
    }  
}


public class GeometricObject {//几何图形
    private String color;
    private double weight;

    public GeometricObject(String color, double weight) {
        this.color = color;
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
    public double findArea(){
        return 0.0;
    }
}
public class Circle extends GeometricObject{
    private double radius;
    public Circle(double radius,String color, double weight) {
        super(color, weight);
        this.radius=radius;

    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    @Override
    public double findArea() {
        return Math.PI*radius*radius;
    }
}
public class MyRectangle extends GeometricObject{
    private double width;
    private double height;
    public MyRectangle(double width,double height,String color, double weight) {
        super(color, weight);
        this.height=height;
        this.width=width;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public double findArea() {
        return height*width;
    }
}
/*
 * 定义一个测试类GeometricTest,
 * 编写equalsArea方法测试两个对象的面积是否相等(注意方法的参数类型,利用动态绑定技术),
 * 编写displayGeometricObject方法显示对象的面积(注意方法的参数类型,利用动态绑定技术)。
 *
 */
public class GeometricTest {

    public static void main(String[] args) {

        GeometricTest geometricTest=new GeometricTest();
        Circle circle=new Circle(2,"white",1.0);
        Circle circle1=new Circle(3,"white",1.0);
        boolean isEquals = geometricTest.equalsArea(circle,circle1);
        System.out.println(isEquals);
        MyRectangle myRectangle= new MyRectangle(2,3,"black",1.0);
        System.out.println(geometricTest.displayGeometricObject(myRectangle));
    }
    public double displayGeometricObject(GeometricObject o) {//GeometricObject o = new Circle(...)
        return o.findArea();
    }

    public boolean equalsArea(GeometricObject o1, GeometricObject o2) {
        return o1.findArea() == o2.findArea();
    }
}

5.5.8 继承成员变量和继承方法的区别:实例说明:

        ①.若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中:编译看左边,运行看右边

        ②.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量:编译运行都看左边



 5.6 Object类的使用

5.6.1 Object类的概述

        Object类是所有Java类的根父类,只声明了一个空参的构造器         

        如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类        

5.6.2 Object类的方法

        Object类中的功能(属性,方法)就具有通用性。

        属性:无

        方法:equal() / toString() / getClass() / hashCode() / clone() / finalize() / wait() / notify() / notifyAll()

5.6.3 equal()方法的使用

        面试题: == 和equals( )的区别

                ①.” == “可以使用在基本数据类型变量和引用数据类型变量中

                        如果比较的是基本数据类型,比较两个变量保存的数据是否相等。(不一定类型要相同)

                        如果比较的是引用型数据变量,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体(类型要相同)


基本数据类型比较

         引用型数据变量


                ②. equals( )是一个方法,而非运算符,只能适用于引用数据类型

                                Object类中的equlas( )的定义:  

public boolean equals(Object obj) {
    return (this == obj);
}
//说明:Object类中定义的equlas( )和 == 的作用是相同的,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体

                而String,Date,File,包装类等都重写了Obejct类中的equals( )方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的”实体内容“是否相同。

public class test {

    public static void main(String args[]) {

        Kids kids1 = new Kids(1);
        Kids kids2 = new Kids(1);
        boolean equals = kids1.equals(kids2);//false
        System.out.println(equals);
       

        String s1 = new String("a");
        String s2 = new String("a");
        boolean equals1 = s1.equals(s2);//true
        System.out.println(equals1);
    }
}


       

5.6.4 重写equlas( )方法

        通常情况下,我们自定义类中使用equlas( )方法也是为了比较”实体内容“是否相同,那么我们就需要对在自定义类中对equlas( )方法进行重写,重写的原则是比较两个对象的实体是否相同。

//自定义类中equals()方法的重写
//Class :自定义类的类名
//a :自定义类中的变量名
@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Class cla = (Class) o;
        return a == cla.a;
    }


5.6.5 equlas( )方法的练习实例



//练习1
import java.util.Objects;

public class Oder {
    private int orderId;
    private String orderName;
    
    public Oder() {
    }

    public Oder(int orderId, String orderName) {
        this.orderId = orderId;
        this.orderName = orderName;
    }

    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    public String getOrderName() {
        return orderName;
    }

    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }

    //重写Object父类的equals()方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Oder oder = (Oder) o;
        return orderId == oder.orderId && Objects.equals(orderName, oder.orderName);
    }

}
public class OderTest {
    public static void main(String[] args) {
        Oder oder1 = new Oder(88, "lisi");
        Oder oder2 = new Oder(88, "lisi");
        System.out.println(oder1.equals(oder2));//结果为:true
    }
}


点击进入:下一节:JavaEE 学习笔记 面向对象(中) 13

Guess you like

Origin blog.csdn.net/woailuo8214/article/details/121299702