javascript动态绑定

介绍

先来看看ai的解释

动态绑定机制是面向对象编程中的一个核心概念,特别是在Java这样的语言中。它允许在运行时根据对象的实际类型来决定调用哪个方法,而不是在编译时。这是多态性的关键特性之一。
在Java中,动态绑定是通过方法调用和方法执行的两个阶段来实现的:
1. **方法调用**:当调用一个对象的方法时,JVM(Java虚拟机)会查看对象的实际类型来决定哪个方法实现应该被调用。如果这个方法在对象的类中被重写,JVM会调用这个重写的方法。这个过程发生在运行时,因为它需要考虑对象的具体类型。
2. **方法执行**:一旦JVM确定了要调用的方法,它就会执行这个方法。在这个过程中,JVM会使用对象的实际类型来查找和执行正确的方法。
动态绑定的关键在于,它允许子类提供特定于自己类型的行为,即使是通过父类的引用来调用方法。这意味着,如果你有一个父类引用指向一个子类对象,当通过这个引用调用一个方法时,实际执行的是子类中定义的那个版本的方法(如果子类重写了这个方法的话)。
为了使动态绑定工作,Java使用了 invokevirtual 指令,这是Java字节码指令集的一部分。当JVM执行 invokevirtual 指令时,它会动态地确定应该调用哪个方法。
这里有一个简单的例子来说明动态绑定:
```java
class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}
class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}
public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 创建一个Dog对象的引用,但是引用类型是Animal
        animal.sound(); // 这将调用Dog类中的sound方法,输出 "Dog barks"
    }
}
```
在这个例子中,尽管 `animal` 的引用类型是 `Animal`,但是实际的对象是 `Dog` 类型。因此,当调用 `animal.sound()` 方法时,会动态绑定到 `Dog` 类的 `sound` 方法,输出 "Dog barks"。这就是动态绑定的魔力所在。
 

个人理解,这里还是离不开我们的编译类型和运行类型。动态绑定是绑定我们的运行类型,并且只对方法进行执行。对于属性则是在哪个类声明就用属性

实操代码

父类和子类

package hansunping;

//创建父类
public class person {
  //简单的创建两个属性
  private String name;
  private int age;

  //创建行为方法,方法中调用创建的say方法
  public void haviours(){
      say();
  }
  //创建方法
  public void say(){
      System.out.println("我是人类!!!");
  }

}
//blog.csdn.net/YYniannian/article/details/126222600
//创建子类
class Student extends person {//如果没有指定访问修饰符,默认情况下该类具有包私有(package-priva
	//te)访问级别,这意味着它只能在同一个包(package)内被访问。
  //创建学生的属性
  private int  score;
  //重写行为
//  public void haviours(){
//      say();
//  }
  //重写say方法
  public void say(){
      System.out.println("我是学生!!!");
  }
}

分析,我们可以从这里看到父类有haviours,say方法。子类同样有haviour方法和say方法。并且haviour方法调用了say方法。

主类

我们在主类中

package hansunping;

public class demon1 {
	public static void main(String[] args) {
		 person student = new Student();
	        //调用学生的say()方法,由于我们的编译类型是Person类,而运行类型是Student类,而动态绑定机制是绑定运行类型。
	        //所以,当我们调用say()方法时,是调用Student类的say()方法
	        student.haviours();//返回“我是学生”
	        //、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
	        //如果我们将student类的say()方法注销,他寻找student类的say方法无果后,会再向它的父类调用say方法。返回我是人类,效果等同于
	
	}

}

person student = new Student();

person是编译类型。student是运行类型。我们的动态绑定就是与运行类型有关的。

在不注释子类的haviour方法时运行结果为

我是学生!!!

在注释之后结果  还是我是学生!!!

为什么呢?

因为子类的haviou方法不存在。那么根据我们的多态的继承寻找规则,我们就找到了父类的haviou方法。在父类的haviou方法中也是调用了say方法的。那么这个say方法是父类的吗?不是,这个方法应该是子类的。即运行类型的类方法。这里要弄懂编译类型和运行类型

接下来我们看另外一个

代码

package hansunping;

//创建父类
public class person {
  //简单的创建两个属性
  private String name;
  private int age;
  public int i =10;
  public int sum() {
	  return getl()+10;	
}
  public int sum1() {
	  return i+10;	
}
  public int getl() {
	  return i;	
}



}
//blog.csdn.net/YYniannian/article/details/126222600
//创建子类
class Student extends person {//如果没有指定访问修饰符,默认情况下该类具有包私有(package-priva
	//te)访问级别,这意味着它只能在同一个包(package)内被访问。
  //创建学生的属性
	  public int i =10;
	  public int sum() {
		  return getl()+20;	
	}
	  public int sum1() {
		  return i+10;	
	}
	  public int getl() {
		  return i;	
	}

}

主类


public class demon1 {
	public static void main(String[] args) {
		 person student = new Student();
	        //调用学生的say()方法,由于我们的编译类型是Person类,而运行类型是Student类,而动态绑定机制是绑定运行类型。
	        //所以,当我们调用say()方法时,是调用Student类的say()方法
//	        student.haviours();//返回“我是学生”
		 System.out.println(student.sum());
		 System.out.println(student.sum1());
	        //、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
	        //如果我们将student类的say()方法注销,他寻找student类的say方法无果后,会再向它的父类调用say方法。返回我是人类,效果等同于
	
	}

}

运行结果

30

20

好,现在我们同样注释掉子类的sum方法

结果

20

20

那么20是怎么来的,分析一下。student从子类中找不到sum方法,所以从父类找。父类有

  public int sum() {
	  return getl()+10;	
}

这个,那么这个get1()+10中的getl是父类的还是子类的方法呢?我将父类的

public int i =20;

i为20.如果是父类的话 那么应该是30了。动态绑定即允许环境还是在子类那里。而编译类型是个引用了,这个时候我们要看内存地址而不是指向的引用

我再在子类中添加;

public int getl() {

return i+1000;

}

结果为

1020

20

我们来验证下属性,我将子类的

public int sum() {

return i+30;

}

改成了i+30,发现结果为50

50

20.说明属性还是不变了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/697126.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安卓事件交互(按键事件、触摸事件、手势识别、手势冲突处理)

本章介绍App开发常见的以下事件交互技术,主要包括:如何检测并接管按键事件,如何对触摸事件进行分发、拦截与处理,如何根据触摸行为辨别几种手势动作,如何正确避免手势冲突的意外状况。 按键事件 本节介绍App开发对按…

人脸考勤项目实训

第一章 Python-----Anaconda安装 文章目录 第一章 Python-----Anaconda安装前言一、Anaconda是什么?二、Anaconda的前世今生二、Windows安装步骤1.官网下载2.安装步骤安装虚拟环境 总结 前言 工欲善其事必先利其器,项目第一步,安装我们的环境…

Mysql的底层实现逻辑

Mysql5.x和Mysql8性能的差异 整体性能有所提高, 在非高并发场景下,他们2这使用区别不大,性能没有明显的区别。 只有高并发时,mysql8才体现他的优势。 2. Mysql数据存储结构Innodb逻辑结构 数据选用B树结构存储数据&#xff0…

基于STM32的595级联的Proteus仿真

文章目录 一、595级联1.题目要求2.思路3.仿真图3.1 未仿真时3.2 模式A3.2 模式B3.3 故障模式 二、总结 一、595级联 1.题目要求 STM32单片机,以及三个LED灯对应红黄绿灯,IIC的OLED显示屏,温湿度传感器DHT11,两个独立按键和两个5…

深度学习的实用性探究:虚幻还是现实?

深度学习的实用性探究:虚幻还是现实? 深度学习作为人工智能领域的一个热点,已经在学术和工业界引起了广泛的关注。尽管深度学习技术显示出惊人的性能和潜力,但有时它们给人的感觉是“虚”的,或许是因为它们的抽象性和…

react修改本地运行项目的端口

一、描述 如果你想让项目在你想要的端口打开的话,就需要进行设置 二、代码 设置一下pages.json文件就可以了,如下: 如果想打开项目不需要点击下面的链接地址,让他运行npm run dev之后自己直接打开到浏览器的话,在后…

猫头虎分享已解决Bug || Uncaught TypeError: Cannot set property ‘innerHTML‘ of null**

猫头虎分享已解决Bug || Uncaught TypeError: Cannot set property ‘innerHTML’ of null** 原创作者: 猫头虎 作者微信号: Libin9iOak 作者公众号: 猫头虎技术团队 更新日期: 2024年6月6日 博主猫头虎的技术世界 &#x…

盘点2024年5月Sui生态发展,了解Sui近期成长历程!

2024年5月是Sui的第一个生日月,Sui迎来了它的上线一周年纪念日。在过去的一年中Sui在技术进步与创新、生态系统的扩展、社区发展与合作伙伴关系以及重大项目和应用推出方面取得重要进展,展示了其作为下一代区块链平台的潜力。 以下是Sui的近期成长历程集…

一、Electron 环境初步搭建

新建一个文件夹,然后进行 npm init -y 进行初始化,然后我们在进行 npm i electron --save-dev , 此时我们按照官网的教程进行一个初步的搭建, 1.在 package.json 文件进行修改 {"name": "electron-ui","version…

pyqt QlineEdit内部增加按钮方法

按钮放在QlineEdit内部,界面更紧凑,体现了按钮和文本框的强关联。 def addButton(self,lineEdit):btn QtWidgets.QPushButton("")icon1 QtGui.QIcon()icon1.addPixmap(QtGui.QPixmap(":/image/images/th.png"), QtGui.QIcon.Norm…

同盾中文点选验证码识别方法

中文验证码一直是识别的难题,首先他分类的种类很多,常见中文都有3500个,而且一般中文验证码都会有变形,导致每一个文字都需要大量训练样本。假设每一个汉字样本需要100个,100350035万个样本,所以标记的样本…

DeepSORT(目标跟踪算法)中的数值表格与调参的关系

DeepSORT(目标跟踪算法)中的数值表格与调参的关系 flyfish DeepSORT(目标跟踪算法)中的马氏距离详解(很详细) DeepSORT(目标跟踪算法)中 可以设置阈值进行异常检测或目标跟踪的原…

【最新鸿蒙应用开发】——类Web开发范式1——生命周期

兼容JS的类Web开发范式 类Web命令式开发的生命周期 1. 应用生命周期 1.1. app.js 每个应用可以在app.js自定义应用级生命周期的实现逻辑,包括: onCreate:在应用生成时被调用的生命周期函数。 onDestroy:在应用销毁时被调用的生…

使用 C# 学习面向对象编程:第 2 部分

C# 类属性简介 属性在面向对象编程中起着至关重要的作用。它们允许我们从类外部访问类的私有变量。在类中使用私有变量是很好的。属性看起来像变量和方法的组合。属性有部分:“get 和 set”方法。get 方法应该返回变量,而 set 方法应该为其赋值。 步骤…

技术前沿 |【大模型InstructBLIP进行指令微调】

大模型InstructBLIP进行指令微调 一、引言二、InstructBLIP模型介绍三、指令微调训练通用视觉语言模型的应用潜力四、InstructBLIP的指令微调训练步骤五、实验结果与讨论六、结论与展望 一、引言 随着人工智能技术的快速发展,视觉语言模型(Vision-Langu…

【Java】解决Java报错:ArrayIndexOutOfBoundsException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 直接访问数组越界2.2 循环中的索引错误2.3 多维数组的错误访问 3. 解决方案3.1 检查数组长度3.2 正确使用循环3.3 多维数组的正确访问 4. 预防措施4.1 使用增强型 for 循环4.2 编写防御性代码4.3 单元测试 结语 引言 在Java编程…

C++ volatile实现原子性读写

__declspec(selectany) 支持h文件定义全局变量,重复包含不报错 int i 2; //变量i还是不用加volatile修饰 #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) #define READ_ONCE(x) ACCESS_ONCE(x) #define WRITE_ONCE(x, val) ({ ACCESS_ONCE(x) (va…

让GNSSRTK不再难【第一天】

第1讲 GNSS系统组成以及应用 北斗导航科普动画_哔哩哔哩_bilibili 1.1 GNSS系统 1.1.1 基本概念 全球卫星导航系统(Global Navigation Satellite System, GNSS),是能在地球表面或近地空间的任何地点为用户提供全天候的三维坐标、速度以及…

redis常用设计模式

Redis常用的设计模式分为读,写,读写三种 一、概要说明 读操作 Read Through Pattern 读穿透 写操作 以Redis统一视图为准:先更新缓存,后更新数据库。 Write Through Pattern 直写模式(首先将数据写入缓存&#xf…

C语言 | Leetcode C语言题解之第135题分发糖果

题目&#xff1a; 题解&#xff1a; int candy(int* ratings, int ratingsSize) {int ret 1;int inc 1, dec 0, pre 1;for (int i 1; i < ratingsSize; i) {if (ratings[i] > ratings[i - 1]) {dec 0;pre ratings[i] ratings[i - 1] ? 1 : pre 1;ret pre;inc…