java学习——多态

目录

一、认识多态

1、概念

2、编译时多态

3、运行时多态

二、instanceof 运算符

认识使用

三、Object类的常用方法

1、认识getClass()

2、认识hashCode()

3、认识equals(Object obj)

4、认识 toString() 

5、认识 finalize()


一、认识多态

1、概念

继承、接口都是多态的具体体现方式,多态主要体现在类别、做事的方式上。多态是面向对象的三大特征之一,多态分为编译时多态和运行时多态两大类。

2、编译时多态

方法重载在编译时就已经如何调用,因此方法重载属于编译时多态。

例子

package calculate;

public class Calclate {
    public int calculate(int a,int b){
        return a+b;
    }

    public double calculate(double a,double b){
        return a+b;
    }
}

package calculate;

public class Calculator {
    public static void main(String[] args) {
        Calclate p1=new Calclate();
        int a=p1.calculate(1,2);
        System.out.println(a);

        Calclate p2=new Calclate();
        double b=p2.calculate(1.3,2.6);
        System.out.println(b);
    }
}

3、运行时多态

Java虚拟机(JVM)为每个变量中引用的对象调用适当的方法。它不会调用由变量类型定义的方法。这种行为称为虚拟方法调用, 它说明了Java语言中重要的多态性特征的一个方面。

例子

package calculate;

public class Father {
    public void show() {
        System.out.println("这是父类的show");
    }
}

package calculate;

public class Child extends Father{
    @Override
    public void show() {
        System.out.println("这是子类的show");
    }
}

package calculate;

public class fatherTest {
    public static void main(String[] args) {
        //变量f的类型是Father
        Father f = new Child();
        //f调用show()时,不会调用Father定义的方法
        f.show();
    }

}

二、instanceof 运算符

认识使用

instanceof本身已是表示的是什么什么的一个实例。 主要应用在类型的强制转换上面。在使用强制类型转换时,如果使用不正确,在运行时会报错。而instanceof运算符对转换的目标类型进行检测,如果是,则进行强制转换。这样可以保证程序的正常运行。
语法

 对象名  instanceof  类名;

//表示检测对象是否是指定类型的一个示例,返回值类型是boolean类型。

例子

package com.first.text.aniaml;

public abstract class Animal {
    public void eat(){ }
}

package com.first.text.aniaml;

public class Monkey extends Animal{
    @Override
    public void eat() {
        System.out.println("猴子吃水果");
    }

    //子类特有方法
    public void climbing(){
        System.out.println("猴子爬树");
    }
}

package com.first.text.aniaml;

public class Panda extends Animal{
    @Override
    public void eat() {
        System.out.println("熊猫吃竹子");
    }

    //子类特有方法
    public void sleep(){
        System.out.println("熊猫睡觉");
    }
}

package com.first.text.aniaml;

public class Tiger extends Animal{
    @Override
    public void eat() {
        System.out.println("老虎吃肉");
    }

    //子类特有方法
    public void strolling(){
        System.out.println("老虎在散步");
    }
}

package com.first.text.aniaml;

public class FeedAnimal {
    public void ZoonKeeper(Animal animal){
        animal.eat();
        //如果animal对象是一个Panda类的实例
        if(animal instanceof Panda){
            ((Panda) animal).sleep();
        }
        //如果animal对象是一个Tiger类的实例
        if (animal instanceof Tiger){
            ((Tiger) animal).strolling();
        }
        //如果animal对象是一个Monkey类的实例
        if (animal instanceof Monkey){
            ((Monkey) animal).climbing();
        }
    }
}

package com.first.text.aniaml;

public class AnimalTest {
    public static void main(String[] args) {
        FeedAnimal p1=new FeedAnimal();
        FeedAnimal p2=new FeedAnimal();
        FeedAnimal p3=new FeedAnimal();

        p1.ZoonKeeper(new Panda());
        p2.ZoonKeeper(new Tiger());
        p3.ZoonKeeper(new Monkey());
    }
}

三、Object类的常用方法

引入:Object类中定义的方法大多数都是属于native方法,native表示的是本地方法,实现方式是在C++中的。

1、认识getClass()

 public  final  class  getClass()

// getClass()方法返回一个class对象,该对象具有可用于获取有关该类的信息的方法,例如

//其名称( getSimpleName() ),其超类( getSuperclass() ),及其实现的接口( getInterfaces() )。

例子

package com.oxi.abstractclass;

public class AnimalTest {
    public static void main(String[] args) {
        String s="s";
        Class stringClass=s.getClass(); //返回一个class对象,该对象具有可用于获取有关该类的信 
        //息的方法
        Class[] interfaceClasses=stringClass.getInterfaces();
        for (int i=0;i<interfaceClasses.length;i++){
            Class interfaceClass=interfaceClasses[i];
            String interfaceName=interfaceClass.getSimpleName(); //获取类名
            System.out.println(interfaceName);
            String interfaceClassNane=interfaceClass.getName(); //获取类的全限定名
            System.out.println(interfaceClassNane);
        }
    }
}

2、认识hashCode()

 public  int  hashCode()

 

//hashCoode() 的返回值是对象的哈希码,即对象的内存地址(16进制)。

 

//根据定义,如果两个对象相等,则它们的哈希码也相等。如果重写了equals() 方法,则会更

//改两个对象的相等方式,并且Object的 hashcode() 实现将将不再有效。因此如果重写了

//equals() 方法,那么他的hashCode() 方法也要进行重写。

强调:Object类中的hashCode()方法返回的就是对象的内存地址。一旦重写hashCode()方法,那么0bject类中的hashCode()方法就是失效,此时的hashCode()方法返回的值不再是内存地址。根据定义,如果两个对象相等,则它们的哈希码也必须相等,反之则不然。

例子

package com.oxi.abstractclass.hashcode;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

 //hashCode()方法被重写后,返回值就不是对象的内存地址了
    @Override
    public int hashCode() {
        return name.hashCode()+age;
    }
}

package com.oxi.abstractclass.hashcode;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

public class StuTest {
    public static void main(String[] args) {
        Student s1 = new Student("ash", 26);
        Student s2 = new Student("ash", 26);
}

3、认识equals(Object obj)

 public  boolean  equals (Object obj)

 

//equals()方法比较两个对象是否相等,如果相等则返回true。object类中提供的equals()方法

//使用身份运算符 (==) 来确定两个对象是否相等。

//对于原始数据类型,这将给出正确的结果。但是, 对于对象,则不是。object提供

//的equals()方法测试对象引用是否相等,即所比较的对象是否完全相同。

//要测试两个对象在等效性上是否相等(包含相同的信息) ,必须重写equals ()方法。

例子

package com.oxi.abstractclass.hashcode;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //如果两个对象相等,那么它们的哈希码一定相等,反之则不然。
    /**如果重写了equals方法,那么一定要重写hashCode方法,因为不重写hashCode方法,
     * 就会调用Object类中的hashCode方法,得到的是内存地址。不同对象的内存地址是
     * 不一致的。但是equals方法重写后,比较的不是内存地址,而是对象的内部信息,这样
     *就会造成多个不同的对象相等却拥有不同的哈希码。
     */

    //1、比较内存地址
    //2、检测是否是同一类型
    //3、检测属性是否相同
    @Override
    public boolean equals(Object o) {
        if(this==o) return true;
        //比较类的定义是否一致
        if(this.getClass()!=o.getClass()) return false;
        //类的定义一致,那么对象o就可以被强制转换为Student
        Student other=(Student)o;
        return this.name.equals(other.name)&&this.age==other.age;
    }

    //hashCode()方法被重写后,返回值就不是对象的内存地址了
    @Override
    public int hashCode() {
        return name.hashCode()+age;
    }
}

package com.oxi.abstractclass.hashcode;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

public class StuTest {
    public static void main(String[] args) {
        Student s1 = new Student("ash", 26);
        Student s2 = new Student("ash", 26);
        boolean a = s2.equals(s1);
        System.out.println(a);
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }
}

补充:讨论 == 和 equals 方法的区别

基本数据类型使用==比较的就是两个数据的字面量是否相等。引用数据类型使用==比较的是内存地址,equals方法来自Object类, 本身实现使用的就是==.此时它们之间没有区别。但是0bject类中的equals方法可能被重写,此时比较就需要看重写逻辑来进行。

4、认识 toString() 

 public  String  toString()

 

 // 我们应该始终考虑在类中重写 toString() 方法

//object的toString()方法返回该对象的string表示形式,这对于调试非常有用。对象的string表

//示形式完全取决于对象, 这就是为什么你需要在类中重写toString()。

例子

package com.oxi.abstractclass.hashcode;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
@Override
    public String
    toString() {
        return name+"\t"+age;
    }
}

package com.oxi.abstractclass.hashcode;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

public class StuTest {
    public static void main(String[] args) {
        Student s1 = new Student("ash", 26);
        Student s2 = new Student("ash", 26);
        System.out.println(s1); //toString()方法重写后该行代码输出结果才是“ ash 26 ”
    }
}

5、认识 finalize()

 protected  void  finalize  throws  Throwable

 

//object类提供了个回调方法finalize (),当该对象变为垃圾时可以在该对象上调用该方法。

//object类的finalize()实现不执行任何操作,你可以厦盖finalize ()进行清理,例如释放资源。

例子

package com.oxi.abstractclass.hashcode;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
@Override
    //当一个Student对象变成垃圾可能会被调用
    protected void finalize() throws Throwable {
        this.name=null;
        System.out.println("所有资源已经被释放,可以开始清理了");
    }
}

package com.oxi.abstractclass.hashcode;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

public class StuTest {
    public static void main(String[] args) {
        show();
        //gc=> garbage collector
        System.gc(); //调用系统的垃圾回收器进行回收
        System.out.println("这是最后一行代码了");
    }
    public static void show(){
        //s的对象作用范围只是在show()方法中,一旦方法执行完毕,
        //那么s对象就应该消亡,释放内存
        Student s=new Student("ash",26);
        System.out.println(s);
    }
}

  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值