IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 007—JAVA多态详细讲解(虚与非虚方法) -> 正文阅读

[Java知识库]007—JAVA多态详细讲解(虚与非虚方法)

形成多态 前提条件:
? 1.有继承关系 Chinese extends Programmer

? 2.有方法重写

多态向上转型方法的引用问题
向上转型: 将子类对象赋值给父类的引用
?? 父类???????????? 子类对象
Programmer pro = new Chinese();

? 编译看左边 运行看右边?? 等号 "="

? 编译: javac 写完代码后
? 运行: java? 程序跑起来

注意:
??? 1.多态的向上转型 无法使用 子类自己独有的资源

public class Programmer {
    public void eat(){
        System.out.println("程序员吃饭......");
    }
    public void writeCode(){
        System.out.println("写代码.......");
    }

}
class Chinese extends Programmer{
    @Override
    public void eat() {
                    System.out.println("中国人 爱吃 饺子.....");
    }
        public void taiJi(){

            System.out.println("打太极......");
        }
}
public class Test {
    public static void main(String[] args) {

        int m = 10;
        double d = m;

        Programmer pro = new Chinese();
        pro.eat();
        pro.writeCode();
    }
}

多态在形参上的应用

public class Animal {
    public void play(){
        System.out.println("动物玩");
    }
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Cat extends Animal {
    @Override
    public void play() {
        System.out.println("小猫玩 老鼠......");
    }
    public void catchMouse(){
        System.out.println("小猫抓老鼠......");
    }
}

class Dog extends Animal {
    @Override
    public void play() {
        System.out.println("小狗玩球.....");
    }
    @Override
    public void eat() {
        System.out.println("小狗爱吃骨头.......");
    }
    public void lookHome(){
        System.out.println("小狗看家......");
    }
}
public static void main(String[] args) {
        Cat cat = new Cat();
        cat.play();
        Dog dog = new Dog();
        dog.play();
        showPlay(dog);

    }

    public static void showPlay(Animal animal){// = new Dog() 或  = new Cat()
        animal.play();

    }

多态的应用:应用在形参

? ? ? ? ? ? ? ? ? ? ? ? 父类类型做形参? ?接收任意子类对象

多态应用在数组:

? ? ? ? ? ? ? ? ? ? ? ? ?父类类型作为数组类型? 可以放入任意子类对象

多态? ? 只和方法有关? 与属性无关

public class Animal {
    String name = "Animal";
    public void play() {
        System.out.println("动物玩");
    }
}

class Cat extends Animal {
    String name = "Cat";

    @Override
    public void play() {
        System.out.println("小猫玩 老鼠......");
    }

    public void catchMouse() {
        System.out.println("小猫抓老鼠......");
    }
}

class Dog extends Animal {
    @Override
    public void play() {
        System.out.println("小狗 玩 球...........");
    }

    public void lookHome() {
        System.out.println("小狗看家......");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal a = new Cat();
        System.out.println(a.name);

    }
}

父类和子类都有name属性但是结果运行出来的是Animal

多态 只和方法有关 与属性无关

向下转型:在向上转型之后? 想要使用子类自己独有的资源(方法和属性)

?小的数据类型? 变量名 = (小的数据类型)大的数据类型的值;

? int m = 10;
? double d? = m;

? int m1 = (int)d;

注意:
??? 1.向下转型 有可能会发生 ClassCastException 类型转换异常

?当需要使用子类中独有的方法时需要向下转型,当需要使用子类的属性的时候需要向下转型;

虚方法与非虚方法

非虚方法:不能重写的方法

????????(1)由invokestatic指令调用的static方法,这种方法在编译时确定在运行时不会改变。

?????????(2)由invokespecial指令调用的方法,这些方法包括私有方法,实例构造方法,这些方法也是在编译时已经确定,在运行时不会再改变的方法

? ? ? ? ? ?(3)由final关键字修饰的方法。虽然final方法是由invokevirtual指令进行调用的, 但是final修饰的方法不能够进行在子类中进行覆盖,所有final修饰的方法是不能够在运行期进行动态改变的。在java语言规范中明确规定final方法就是非虚方法。

虚方法: 能/可以重写的方法

静态分配:看形参最匹配
动态绑定: 执行重写后

案例一:

class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
	public void method(Daughter f) {
		System.out.println("daughter");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}

//静态分配   实参编译时类型 与形参最匹配
public class TestOverload {
	public static void main(String[] args) {
		Father f = new Father();
		Father s = new Son();
		Father d = new Daughter();
        
     MyClass my = new MyClass();
		my.method(f);//father
		my.method(s);//father  son
		my.method(d);//father daughter
	}
}

静态分配:看形参最匹配

动态绑定: 执行重写后

案例二:

class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}
public class TestOverload {
	public static void main(String[] args) {
		MyClass my = new MyClass();

		Father f = new Father();
		Son s = new Son();
		Daughter d = new Daughter();


		my.method(f);//father
		my.method(s);//son
		//父类类型做形参可以接受子类对象

		my.method(d);//father
	}
}

案例三:

class MyClass{
    public void method(Father f) {
        System.out.println("father");
    }
    public void method(Son s) {
        System.out.println("son");
    }
}
class MySub extends MyClass{
    public void method(Daughter d) {
        System.out.println("daughter");
    }
}
class Father{

}
class Son extends Father{

}
class Daughter extends Father{

}
public class TestOverload {
    public static void main(String[] args) {
        //多态向上转型
        MyClass my = new MySub();

        Father f = new Father();
        Son s = new Son();
        Daughter d = new Daughter();

        my.method(f);//father

        my.method(s);//son

        my.method(d);//father
    }
}

重写的时候形参列表必须一样

案例四

class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
}
class MySub extends MyClass{
	public void method(Father d) {//重写的
		System.out.println("sub--");
	}
	//新增的
    public void method(Daughter d) {
		System.out.println("daughter");
	}
}
class Father{
}
class Son extends Father{
}
class Daughter extends Father{
}
public class TestOverloadOverride {
    public static void main(String[] args) {
        //多态向上转型
        MyClass my = new MySub();
        //创建对象
        Father f = new Father();
        Son s = new Son();
        Daughter d = new Daughter();

        my.method(f);//sub  sub      sub
        my.method(s);//sub  son      son
        my.method(d);//father father sub
    }
}

native关键字

native:本地的原生的

修饰方法? 本地方法
java 不是万能的 某些功能无法实现的 借助于 C/C++ 语言实现

本地方法没有方法体
? public native int hashCode();

虚拟机栈

本地方法栈:存储调用本地方法时的相关信息

final关键字

final修饰的类? 不能有子类
????? public final class Animal {}

final修饰的方法不能被重写
??????? public final void show(){}

final修饰的变量是常量

?? final修饰的成员变量 必须有显示赋值的操作(要么直接赋值,要么在构造器中赋值),总之,必须有值。

final修饰的对象地址值不能改变

?Object类

1.如果一个类没有显示的继承另一个类那么此类必然继承 Object 类
2.数组的父亲也是Object
3.任何对象都可以与Object 写成多态的形式

getClass: 获取运行时类型

hashcode()

?hashCode():返回一个哈西码 散列值 哈西表:顺序表+链表组成

哈西码不同 对象肯定不同

哈西码相同同 对象不一定相同

为什么重写hashCode()? 如果两个对象的属性值完全一样 那么认为是同一个对象 如果是同一个对象 哈西码要相同 对hashCode()重写(否则不重写的情况下会导致永远调用的时native下的hashcode(),native的话只要new就会不一样)

?

?哈希表为了提高查询和存储的效率的,先用哈希值找到顺序表中的位置,在用equals比较在链表中的具体位置。

哈希表中存储的数据是无序唯一的

public class Person {

    String name;
    int age;

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



    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 20);

        System.out.println("p1.hashCode() = " + p1.hashCode());
        Person p2 = new Person("张三", 20);

        System.out.println("p2.hashCode() = " + p2.hashCode());


        System.out.println("Aa---->"+"Aa".hashCode());
        System.out.println("BB---->"+"BB".hashCode());
    }
}

equals方法

==:
??? 比较基本数据类型 比较的是值
??? 比较的是对象? 比较的是地址值

equals:
??? 重写前:比较的是对象的地址值 this == obj

????????????????public boolean equals(Object obj) {
??? ????????????????????????return (this == obj);
????????????????????????}

??? 重写后: 比较属性值

public class Person {
    String name;
    int age;

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

    /*@Override
    public boolean equals(Object o){
        if (this == o){return true ; }
        if (o == null && this.getClass() != o.getClass()){
            return false;
        }
       Person person = (Person)o;
        return age == person.age && Objects.equals(name, person.name);
    }*/

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode(){
        return Objects.hash(name,age);
    }

}

?toString方法

输出对象时默认会调用对象的toString方法

全类名+@+16进制的哈希码

com.atguigu.object.tostring.Student@4554617c

public class Student {
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args) {

        Student s1 = new Student("李白", 20);

        System.out.println(s1);

        String s = s1.toString();
        System.out.println(s);

    }
}

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-23 12:20:41  更:2021-10-23 12:21:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:11:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码