Java 基础 --- Java变量储存机制及参数传递

2023-11-04

JVM内存机制

在这里插入图片描述

在这里插入图片描述

Primitive type的储存和值传递

primitive type的储存

  • primitive type的局部变量是储存在JVM stack上, 首先JVM创建一个名为A的变量, 存在于局部变量表中,然后去栈中查找是否存有字面量值为10的内容,如果有就直接把A指向这个地址. 如果没有,JVM会在栈中开辟一块空间来存储10这个内容.
  • 当写下 int A = 10 时:
    在这里插入图片描述
  • 当写下 int A = 10, int B = 10 时:
    在这里插入图片描述
  • int A = 10, int B = 10, B = 20;
    在这里插入图片描述

primitive type的值传递

  • 如下图,在执行main方法时,JVM会在栈顶加进一个栈帧,此栈帧包括一个A=10的变量。在执行passPrimitive方法时,JAM会再加入一个新的栈帧,此栈帧包括一个B=10的变量,当执行B=100时,在passPrimitive栈帧中的B值会被改变,但在main栈帧中的A值不会被改
    在这里插入图片描述
  • Before: A is 10
  • B is 100
  • After: A is 10

Reference Type的储存和值传递

Reference Type的储存

  • reference包括除基础类型之外的其他所有类型,变量中储存的时一个引用(在栈中存一个可以指向heap的引用),具体过程如下
    在这里插入图片描述

Reference Type的传递

  • 会改变实参
    在这里插入图片描述
  • Before: S1’ID is 100
  • In The method: S1’ID is 200
  • After: S1’ID is 200
  • 当执行第21行(Student s1 = new Student())时
    在这里插入图片描述
  • 当执行第24行时(进入Test方法)
    在这里插入图片描述

总结:

  • 在Java中没有引用传递,只有值传递。在Java中“值”的概念分为两种,一个是基础类型的实际数值,一个是引用,但是对于任何一种变量Java都拿不到地址(引用变量只是储存的是引用, 但是变量本身的地址是拿不到的, 也就是说Java中对对象的引用本身做不了任何操作,比如替换成另外一个引用)所以不存在引用传递。反之,在C++/C中对于任何一个变量(基础变量,类,指针变量等)除了可以拿到变量里的值以外还可以拿到变量的地址,所以有值传递,引用传递,指针传递之分

关于包装类的参数传递问题: Integer as example

  • 虽然所有的包装类都是引用传递,但是在函数中传递包装类并不能改变实参
  • 因为所有的包装类都是不可变类, 也就是用final修饰, 比如final int value. 所以当对象被重新赋值时,会生成新的对象
  • 根据Integer的缓存机制,如果在-128-127之间 就从常量池中获取一个Integer对象返回;如果不在范围内 会new Integer(value)返回
public class ValuePassing {
	
	public static void fun1(Integer i) {
		System.out.println("在fun1中赋值前i的地址是: " + System.identityHashCode(i));
		i = 10; //从常量池中获取一个Integer对象,或者new Integer(value)
		//赋值之后,地址发生改变
		System.out.println("在fun1中赋值后i的地址是: " + System.identityHashCode(i));
	}
	
	public static void main(String[] args) {
        Integer i = 5;
        System.out.println("在main中i的地址是: " + System.identityHashCode(i));
        fun1(i);
        
        i = 20;
        //赋值之后,地址发生改变
        System.out.println("在main中i重新赋值之后的地址是: " + System.identityHashCode(i));
    }
}

output:
在main中i的地址是: 1072591677
在fun1中赋值前i的地址是: 1072591677
在fun1中赋值后i的地址是: 1523554304
在main中i重新赋值之后的地址是: 1175962212

关于缓存:

public class ValuePassing {
	
	public static void fun1(Integer i, Integer j) {
		System.out.println("在fun1中赋值前i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
		//对i和j同时赋予一样的值后(在-128-127之间),地址一样
		i = 10; 
		j = 10;
		System.out.println("-----------------------------------------------");
		System.out.println("在fun1中赋值后i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
	}
	
	public static void main(String[] args) {
        Integer i = 5;
        Integer j = 20;
        System.out.println("在main中i的地址是: " + System.identityHashCode(i));
        System.out.println("在main中j的地址是: " + System.identityHashCode(j));
        System.out.println("-----------------------------------------------");
        fun1(i, j);
    }
}

output:
在main中i的地址是: 1072591677
在main中j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值前i的地址是: 1072591677
在fun1中赋值后j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值后i的地址是: 1175962212
在fun1中赋值后j的地址是: 1175962212
public class ValuePassing {
	
	public static void fun1(Integer i, Integer j) {
		System.out.println("在fun1中赋值前i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
		
		//不在-128-127之间地址则不一样
		i = 1000; 
		j = 1000;
		System.out.println("-----------------------------------------------");
		System.out.println("在fun1中赋值后i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
	}
	
	public static void main(String[] args) {
        Integer i = 5;
        Integer j = 20;
        System.out.println("在main中i的地址是: " + System.identityHashCode(i));
        System.out.println("在main中j的地址是: " + System.identityHashCode(j));
        System.out.println("-----------------------------------------------");
        fun1(i, j);
    }
}

output:
在main中i的地址是: 1072591677
在main中j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值前i的地址是: 1072591677
在fun1中赋值后j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值后i的地址是: 1175962212
在fun1中赋值后j的地址是: 918221580
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 基础 --- Java变量储存机制及参数传递 的相关文章

随机推荐

  • 程序获取

    程序获取 机器学习 深度学习程序和数据获取方式 目录 程序获取 机器学习 深度学习程序和数据获取方式 程序获取方式1 程序获取方式2 程序获取方式3 程序获取方式4 程序获取方式5 程序获取方式6 程序获取方式1 私信博主或者博客底部联系博
  • jmeter线程组内的接口顺序执行解决办法

    一 压力测试场景分析 测试人员在使用jmeter对一个场景进行压力测试 在一个线程组内有多个接口时 测试人员想要测试在特定的时间段内一直循环该线程以测试服务器压力 但是jmeter在run线程组的时候 经常不会按照该线程组内的接口顺序执行
  • Ubuntu torch.cuda.is_available() 返回 False情况

    如果Ubuntu20 04 出现torch cuda is available 返回 False情况 解决方法 重新安装Pytorch Ubuntu20 04 CUDA 11 4 Pytorch配置安装 conda conda create
  • Hibernate 自动创建表

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到教程 1 在 hibernate cfg xml 添加这句话 可以自动生成数据表
  • 开放集识别的最新进展总结(源于Recent Advances in Open Set Recognition: A Survey)

    摘要 在现实的识别 分类任务中 由于受到各种客观因素的限制 在训练一个识别器或分类器摘 0 摘要 原因与场景 在现实的识别 分类任务中 训练模型的时候可能并没有所有类别的训练集 因此 这样训练出来的模型在没有出现过的类出现时 一般会失效 解
  • 中国科学院大学工程管理与信息技术学院 2014年招收以下八个领域在职工程硕...

    中国科学院大学工程管理与信息技术学院2014年招收以下八个领域在职工程硕士 欢迎广大考生报考 一 专业领域介绍 招生领域 研究方向 学费 报考条件 学位 证书 学习方式
  • 数据结构与算法——栈的实现及模拟

    目录 一 栈的原理 二 栈的实现 1 栈的定义 2 栈的初始化 3 入栈 4 出栈 5 获取栈顶元素 6 栈的大小 7 判断栈是否为空 8 栈的销毁 一 栈的原理 堆栈 英语 stack 又称为栈或堆叠 是计算机科学中的一种抽象资料类型 只
  • Kafka核心设计与实践原理总结:进阶篇

    kafka作为当前热门的分布式消息队列 具有高性能 持久化 多副本备份 横向扩展能力 我学习了 深入理解Kafka 核心设计与实践原理总结 一书后 对其中主要的知识点进行了总结 便于理解和掌握kafka的原理和应用 在这里分享出来 希望也能
  • es常用curl命令

    说明 仅记录实验室测试过程 不作为官方文档使用 可能会有很多地方未能验证 因此无法进行技术兜底 需使用方多加验证测试 涉及到高危需走变更 目前测试版本均为651及以前版本 命令样例基于安全模式 如果是在非安全模式下 将命令中的参数 tlsv
  • .Net Core下简单的JWT黑名单中间件

    自从JWT认证方式在互联网上蔓延后 Session认证方式就被挤掉了一大半的生存空间 这里我们不讲JWT与Session两种方式的优缺点 我们只讲如何通过JWT的黑名单来阻止某些Token的登录 设置黑名单 也就是说要将Token写入某个存
  • gRPC:以 C++为例

    文章目录 1 gRPC 环境搭建 1 1 安装 cmake 1 2 安装 gcc gdb 1 3 安装 gRPC 1 4 protobuf 安装 1 5 测试环境 2 1 grpc 同步 2 1 定义服务 2 2 gRPC 服务端 2 3
  • 通讯录的实现

    ifndef TONGXUNLU H define TONGXUNLU H define MAX NAME 20 define MAX PHONE 11 define MAX PEO 1000 typedef struct PeoInfo
  • python肢体识别线条_【HUSKYLENS二哈识图】micro:bit视觉识别入门教程——06循“轨”蹈矩的麦昆...

    点击上方 蘑菇云创造 可以订阅哦 循 轨 蹈矩的麦昆 功能介绍 本项目利用 HuskyLens 的巡线功能 让麦昆 plus 按照地面上的线路轨道欢快地蹦跶 材料清单 知识园地 如果我们要让小车机器人按照地面上的线条移动 就需要一些传感器来
  • SentencePiece,subword-nmt,bpe算法

    BPE Byte Pair Encoding 双字节编码 2016年应用于机器翻译 解决 集外词 OOV 和罕见词 Rare word 问题 论文题目 Neural Machine Translation of Rare Words wit
  • [动态系统的建模与分析]9_一阶系统的频率响应_低通滤波器

    动态系统的建模与分析 8 频率响应 详细数学推导 G jw 滤波器 运放滤波器 3 反相同相比例放大电路 Multisim电路仿真 运放滤波器 2 运放反馈原理 运放滤波器 1 理想运放 虚短虚断 现代控制理论 11 现代控制理论串讲 完结
  • KDD'23

    大家好 我是kaiyuan 最近大模型LLM的各类信息有种乱花渐欲迷人眼的感觉 刷几篇KDD 23的文章冷静一下 今天分享阿里淘宝搜索的最新工作 发表在KDD 23上 Rethinking the Role of Pre ranking i
  • 学习使用vs2019编写一个Linux c++程序

    前言 前些日子 在centos捣鼓C 程序 6 5版本的GCC4 4实在太旧了 不支持C 11 官方说得升级到GCC4 7以上 于是乎 尝试更新GCC 一顿操作猛如虎 一看战绩0 5 不成功 便成仁 一气之下 整了个Centos8 2 这下
  • VS2010利用MFC的MSCcom控件的方法(WIN8系统)

    1 由于VC6 0之后 VS不在带有MScomm控件 要使用MScomm控件需要自己注册添加 控件下载链接 MScomm控件 压缩包中含有四个文件 MSCOMM SRG MSCOMM32 DEP MSCOMM32 oca mscomm32
  • Clouderera SCM Server启动失败之pam_unix(sshd:session) session closed for user root分析定位

    昨天在某客户环境进行CDH Hadoop的安装 安装还算比较顺利 但在启动Cloudera SCM Server和Agent服务的时候均启动失败 root YXnode01 service cloudera scm server resta
  • Java 基础 --- Java变量储存机制及参数传递

    Java 基础 Java变量储存机制及参数传递 JVM内存机制 Primitive type的储存和值传递 primitive type的储存 primitive type的值传递 Reference Type的储存和值传递 Referen