首页 > 系统相关 >Java中多态的内存

Java中多态的内存

时间:2024-09-27 13:23:43浏览次数:3  
标签:存储 Java 对象 堆区 多态 Dog 内存 Cat

一、内存分配区域

Java内存主要分为栈区、堆区、方法区等区域。

1.栈区:

栈区是Java内存管理中的一个关键区域,它主要用于存储局部变量和方法的执行环境(也称为栈帧)。每个线程在JVM中都有一个私有的栈,用于存储该线程中方法调用的上下文信息。栈区内存主要存放的数据有:局部变量表、操作数栈和动态链接。

局部变量表:包含了方法执行过程中所需的所有局部变量,包括基本数据类型的变量、对象引用等。

操作数栈:用于存放方法执行过程中产生的中间结果,以及计算过程中需要的操作数。它是一个后入先出的栈。

动态链接:每个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接。

2.堆区:

堆区是Java用来存储对象实例和数组的内存区域,它是JVM管理的最大一块内存区域,也是垃圾收集器管理的主要区域。堆区主要存放的数据有:对象实例、数组。

对象实例:通过new关键字创建的任何对象实例都存储在堆内存中。这些对象可以是用户自定义的类实例,也可以是Java库中的类实例。

数组:无论是基本数据类型的数组还是对象类型的数组,都存储在堆内存中。

其中,字符串常量池在JDK1.6的时候位于方法区,1.8之后位于堆区中。而在堆区的介绍中没有明确的列出字符串常量池是因为在现代Java虚拟机的实现中,字符串常量池虽然与堆区有紧密的关系,但它并不直接等同于堆区的一个独立子区域,而是有其特殊的存储和管理方式。实际上,字符串常量池中的字符串对象在物理上存储在堆区中,但JVM通过特定的机制(如字符串表)来管理和维护这些字符串对象,以实现字符串的共享和重用。堆区主要是用于存储对象实例和数组的内存区域,它关注的是对象的分配、回收等内存管理问题。而字符串常量池虽然与堆区有交集(即字符串对象存储在堆中),但它更多地是作为一个特殊的优化手段存在,用于提升字符串处理的性能和减少内存消耗。但1.8之后字符串常量池也是位于堆区中的。

3.方法区:

方法区是JVM中用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。它是所有线程共享的内存区域。方法区主要存放的数据有:类的结构信息、字段和方法数据、JIT编译器编译后的代码。

类的结构信息:包括类的名称、父类的名称、实现的接口、字段描述、方法描述等。

字段和方法数据:类的字段(包括静态变量和实例变量,但仅字段的描述信息存储在方法区,而字段的值存储在其他区域,如静态变量存储在方法区的静态变量区,实例变量存储在堆区)和方法的字节码内容、一些特殊方法(如构造函数、接口方法、虚方法、默认方法等)也存储在方法区。

JIT编译器编译后的代码:如果JVM开启了即时编译(JIT),那么被JIT编译后的本地机器码也会存储在方法区的某个部分。

需要注意的是,静态变量虽然逻辑上属于类,但它们的值(如果是对象或数组)的存储位置在堆上,而静态变量本身(即变量名和类型信息)的描述则存储在方法区。此外,实例变量和局部变量(基本类型或对象引用)的值也存储在堆上(实例变量)或栈上(局部变量),但它们的描述信息(即变量名和类型信息)则与类的结构信息一起存储在方法区。

二、Java中多态的内存

在Java中,多态是面向对象编程的一个重要特性,它允许子类对象被当作父类对象来使用。多态的实现涉及到方法的重写和动态绑定(详见静态绑定和动态绑定)。理解多态的内存模型有助于更好地掌握Java的内部工作机制。

在Java中,对象的内存分配和方法调用涉及到以下几个概念:

  1. 对象实例:实际创建的对象,存储在堆内存中。
  2. 引用变量:指向对象实例的引用,存储在栈内存中。

 实际上这里可以运用动态绑定那一章的代码来解释了,直接复制过来,(加了一丢丢代码~~~)----------------------------源文本在这里->静态绑定和动态绑定

package oneHundredDayPlan.fourDay;
//动态绑定代码示例

class Animal {
    public void dynamicBinding() {
        System.out.println("dynamic binding");
    }
}

class Dog extends Animal {
    @Override
    public void dynamicBinding() {
        System.out.println("dynamic");
    }
}

class Cat extends Animal {
    @Override
    public void dynamicBinding() {
        System.out.println("binding");
    }
}

public class Two {
    public static void main(String[] args) {
        Animal a = new Dog();
        a.dynamicBinding();//dynamic

        Animal b = new Cat();
        b.dynamicBinding();//binding

        Dog dog = new Dog();
        dog.dynamicBinding();//dynamic

        Cat cat = new Cat();
        cat.dynamicBinding();//binding
    }
}

代码详解:

这段代码中,

第一个new Dog();

在堆区中创建了一个Dog对象

第一个new Cat();

在堆区中创建了一个Cat对象 

Dog dog = new Dog();

 在堆区中创建了一个Dog对象

Cat cat = new Cat();

在堆区中创建了一个Cat对象

(是两个Dog对象和两个Cat对象,是不同的对象)

Animal a是一个animal类型的引用,存储在栈内存中,指向堆区中的Dog对象 

Animal b是一个animal类型的引用,存储在栈内存中,指向堆区中的Cat对象 

Dog dog是一个Dog类型的引用,存储在栈内存中,指向堆区中的Dog对象

Cat cat是一个Cat类型的引用,存储在栈内存中,指向堆区中的Cat对象

当调用a.dynamicBinding()方法时,JVM 会检查a引用实际指向的对象类型(Dog),然后调用Dog类的dynamicBinding方法。

当调用b.dynamicBinding()方法时,JVM 会检查b引用实际指向的对象类型(Cat),然后调用Cat类的dynamicBinding方法。

当调用dog.dynamicBinding();时,JVM 会检查dog引用实际指向的对象类型(Dog),然后调用Dog类的dynamicBinding方法。

当调用cat.dynamicBinding();时,JVM 会检查cat引用实际指向的对象类型(Cat),然后调用Cat类的dynamicBinding方法。

标签:存储,Java,对象,堆区,多态,Dog,内存,Cat
From: https://blog.csdn.net/2402_82356599/article/details/142366812

相关文章

  • JavaScript 网页设计经典案例代码全览
    一、响应式导航栏HTML结构:<nav><!--这是一个导航栏的容器--><divclass="logo">YourLogo</div><!--用于显示logo的div元素--><divclass="menu-icon">&#9776;</div><!--显示菜单图标(通常用于触发菜单的显示/隐藏)-->......
  • java窗口登录界面实现随机验证码
    创建窗口内容及验证码更换代码示例:packageframe;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjavax.swing.JButton;importjavax.swing.JFrame;importjavax.swing.JLabel;importjavax.swing.JTextField;publicclassJframeexte......
  • 如何在Java中优雅地处理异常
    在软件开发过程中,异常处理是一个至关重要的环节。良好的异常处理机制不仅能提升程序的健壮性,还能极大地改善用户体验。对于Java开发者来说,掌握如何有效地处理异常是非常必要的。本文将探讨几种在Java中优雅地处理异常的方法。使用try-with-resources语句从Java7开始,引入了try-wit......
  • Java11 新特性
    直接运行在以前的版本中,在命令提示下,需要先编译,生成class文件之后再运行,例如:javacHelloWorld.JavajavaHelloWorld在Java11中,可以这样直接运行,当然这样直接运行是不产生字节码文件的javaHelloWorld.JavaString新增方法1.strip方法:可以去除首尾空格,与之前的trim的区别......
  • Java12 新特性
    升级的switch语句在jdk12之前的switch语句中,如果没有写break,则会出现case穿透现象intmonth=3;switch(month){case3:case4:case5:System.out.println("spring");break;case6:case7:case8:System.out.print......
  • java 学习- spring 全家桶学习与使用教程
    文章目录前言一、Spring全家桶概述二、SpringFramework基础1.核心特性2.Bean管理3.SpringMVC三、SpringBoot快速开发1.简介2.创建项目3.编写应用4.运行与测试四、SpringCloud微服务架构1.简介2.核心组件3.构建微服务五、高级......
  • Java9 新特性
    接口私有方法publicinterfaceMyInterface{//定义私有方法privatevoidm1(){System.out.println("123");}//default中调用defaultvoidm2(){m1();}}可以在接口中声明private修饰的方法了,其实就是为了让default方法......
  • Java如何解决同时出库入库订单号自动获取问题
    在Java中处理同时出库和入库的订单号自动获取问题,通常涉及到多线程环境下的并发控制。为了确保订单号的唯一性和连续性,我们可以使用多种策略,如数据库的自增ID、分布式锁、或者利用Java的并发工具类如AtomicLong等。这里,我将提供一个基于AtomicLong的简单示例,适用于单机环境。1.场......
  • Java如何解决同时出库入库订单号自动获取问题
    在Java中处理同时出库和入库的订单号自动获取问题,通常涉及到多线程环境下的并发控制。为了确保订单号的唯一性和连续性,我们可以使用多种策略,如数据库的自增ID、分布式锁、或者利用Java的并发工具类如AtomicLong等。这里,我将提供一个基于AtomicLong的简单示例,适用于单机环境。1.场......
  • JavaScript 变量的作用域链
    作用域链本质上就是使用的是哪个变量,全局变量,局部变量,自身的变量。这个在看别人代码的逻辑的时候非常有用,底层是变量的查找机制。嵌套关系的作用域窜连起来形成了作用域链在函数被执行,会优先查找当前函数作用域中的变量。如果当前函数作用域找不到,则会逐级查找父级作用域,知道......