为什么说Java不存在引用传递?

在Java语言中,存在两种数据类型,一种是基本类型,如int、byte等8种基本类型,一种是引用类型,如String、Integer等。这两种数据类型区别就在于,基本类型的各个类型大小是固定的,如int类型占4个字节,且数据存储于栈中;而引用类型大小则不固定,根据引用类型的属性构成决定的,且数据存储是在堆中,栈中的变量存储是指向堆中的数据引用;

正是因为有两种数据的存储区别,很多人才容易将值传递和引用传递搞混了。并且容易产生误解,Java数据如果是基本类型就是值传递,如果是对象(引用类型)那就是引用传递,但这是错误的!

值传递和引用传递

在程序语言中是这样定义值传递和引用传递的:

值传递:是在调用函数时将实际参数复制一份到函数中,这样如果对参数进行修改,将不会影响到实际的参数。

引用传递:是指在调用函数时将实际参数地址直接传递到函数中,那么如果函数中对参数进行修改,将影响到实际的参数。

对于上述概念是程序语言中对于值传递和引用传递的通用概念,那我们用代码来验证一下为何说Java是不存在引用传递的。

首先看基本类型的传递

这段代码最后输出是:

这个结果是毫无疑问的,分别输出的pvb是100和1!即使调用了passByValue(int pbV),在方法中改变了pbV的值,但是在main方法中的pbV的值仍然是1,这说明传入passByValue方法的是个拷贝的副本值,在方法中对这个副本值进行修改,不会影响到原变量,证实Java基本类型是值传递

再换成引用类型的看看:

大家猜猜最后会输出什么......如果按照值传递的理论概念,传递给函数的变量应该是拷贝的副本,无论在方法函数中做出什么样的修改,都不会影响到原值,所以按照值传递是不是应该输出两个“Java”字符串?!

但事实上最后输出结果却是“Java”和“Java+python”两个字符串:

难道Java是存在引用传递的?

答案是不存在的!我们来分析上面的程序在内存中的存储:

首先在main方法中创建一个StringBuffter对象,此时buffter变量引用此对象的地址,然后调用passByReference方法,此时,将buffter变量引用的地址拷贝一份副本传入passByReference方法,在passByReference中调用引用对象的append(“+python”)方法,此对象变成了”Java+python”字符串,最后输出main方法输出buffer变量所指向的对象,即”Java+python”字符串;

话说回来,将引用拷贝一份副本传至方法参数中,难道这不算引用传递吗?当然不算!

我们再来读一下引用传递的概念定义:引用传递是指在调用函数时将实际参数地址直接传递到函数中,那么如果函数中对参数进行修改,将影响到实际的参数

事实上,在Java语言中,我们是不能直接获取到实际参数的地址的,我们所使用的都是引用去操作其指向的地址的对象,引用≠实际参数地址,所以在Java语言中不存在引用传递。只是因为在传递引用类型的对象时,拷贝对应的引用值副本进行传参,很多人误以为这就是引用传递,但这其实是值传递。

结论

在Java语言中无论是基本数据类型还是引用类型,都是使用值传递的方式,对于引用传递来说是不存在的。

那最后上一个“硬菜”,下面的这段代码为什么会输出两个一模一样的"Java"字符串呢!如果了解String类型底层的朋友,答案一眼就能看出了,欢迎评论留言。

public class MemberServiceImpl{
void test (int i){
i=3;
}
void testObj (Test test){
test=new Test();
System.out.println(test.getI());
}
public static void main(String[] args) {
MemberServiceImpl memberService=new MemberServiceImpl();
int i=0;
memberService.test(i);
System.out.println("i:"+i); Test test=new Test();
test.setI(111);
memberService.testObj(test);
System.out.println(test.getI());
}
}

运行结果:

i:0

null

111(之所以不是null是因为,testObj方法内外的引用不是同一个,如果不修改引用指向的对象,则操作的是同一个对象)

Java求值策略的更多相关文章

  1. 深入理解JavaScript系列(19):求值策略(Evaluation strategy)

    介绍 本章,我们将讲解在ECMAScript向函数function传递参数的策略. 计算机科学里对这种策略一般称为“evaluation strategy”(大叔注:有的人说翻译成求值策略,有的人翻译 ...

  2. Scala - 快速学习04 - 求值策略

    表达式求值策略(Evaluation Strategy) Scala中所有的运算都是基于表达式的. Call By Value - 对函数实参求值,且仅求值一次:函数调用之前对所有表达式进行求值 Ca ...

  3. Scala基础篇-05求值策略

    Scala的求值策略有2种: call by value call by name 如何区分? 例子: def bar(x:Int,y: => Int) = def loop(): Int=lo ...

  4. 关于java是值传递还是引用传递

    一.概念 实际上对这两种传递方式,知乎上有个回答说得很好: 值传递和引用传递,属于函数调用时参数的求值策略(Evaluation Strategy),这是对调用函数时,求值和传值的方式的描述,而非传递 ...

  5. C#函数式编程之惰性求值

    惰性求值 在开始介绍今天要讲的知识之前,我们想要理解严格求值策略和非严格求值策略之间的区别,这样我们才能够深有体会的明白为什么需要利用这个技术.首先需要说明的是C#语言小部分采用了非严格求值策略,大部 ...

  6. C 语言 - 逻辑运算和短路求值

    逻辑运算符: 运算符 含义 优先级 ! 逻辑非 高 && 逻辑与 中 || 逻辑或 低 举例: !a:如果 a 为真,!a 为假:如果 a 为 假,!a 为真 a && ...

  7. Java 计算数学表达式(字符串解析求值工具)

    Java字符串转换成算术表达式计算并输出结果,通过这个工具可以直接对字符串形式的算术表达式进行运算,并且使用非常简单. 这个工具中包含两个类 Calculator 和 ArithHelper Calc ...

  8. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  9. java实现算术表达式求值

    需要根据配置的表达式(例如:5+12*(3+5)/7.0)计算出相应的结果,因此使用java中的栈利用后缀表达式的方式实现该工具类. 后缀表达式就是将操作符放在操作数的后面展示的方式,例如:3+2 后 ...

  10. 奇怪的表达式求值 (java实现)

    题目参考:http://blog.csdn.net/fuxuemingzhu/article/details/68484749 问题描述; 题目描述: 常规的表达式求值,我们都会根据计算的优先级来计算 ...

随机推荐

  1. 一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.简述Redis事务实现 2.redis集群方案 3.redis主从复制的核心原理 4.CAP理论,BASE理论 5.负 ...

  2. JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题

    1.线程和进程 进程:一个程序,微信.qq...程序的集合.(一个进程包含多个线程,至少包含一个线程.java默认有两个线程:主线程(main).垃圾回收线程(GC) 线程:runnable.thre ...

  3. web3.0、比特币、区块链、元宇宙,以及那些待收割的韭菜们!

    前几天看到周星驰在社交账号上招聘web3.0的人才,感觉有必要说说web3.0,当然不是基于技术层面,而是从另一个维度说说web3.0以及其它相关的概念,从而做到如何反欺诈,如何避免被资本割韭菜.想到 ...

  4. 知识图谱顶刊综述 - (2021年4月) A Survey on Knowledge Graphs: Representation, Acquisition, and Applications

    知识图谱综述(2021.4) 论文地址:A Survey on Knowledge Graphs: Representation, Acquisition, and Applications 目录 知 ...

  5. vue3+element-plus+登录逻辑token+环境搭建

    vue3+element-plus+登录逻辑token环境搭建 安装脚手架工具 1 npm i @vue/cli@4.5.13 -g 验证是否安装成功 1 vue -V # 输出 @vue/cli 4 ...

  6. shardingsphere-jdbc 水平分表学习记录

    放在自己博客里搬过来一份~ 前司使用的是自己魔改的TDDL,在家时间比较多就尝试学一些业内比较常用的中间件. 这里记录一下学习中遇到的一些问题. 环境 设置的比较简单(太懒了就测试了几个表), 两个分 ...

  7. JAVA的File对象

    文件 1.File对象 java封装的一个操作文件及文件夹(目录)的对象.可以操作磁盘上的任何一个文件和文件夹. 2.创建文件  方式一:根据路径构建一个File对象new File(path) // ...

  8. vscode代码部署

    前言 在本地环境中开发代码时,经常需要将代码上传到服务器环境中,在环境中构建并调试程序.如果手动使用scp.ftp等文件传输程序将代码上传至环境,一次两次还好,反复多次操作则有些繁琐. 为了方便进行本 ...

  9. 【网络】博客网站搭建之Typecho(命令版)

    目录 前言 个人博客系统筛选 内网穿透 安装nginx 安装PHP 安装mysql Typecho 环境安装 参考 安装typecho Nginx与PHP进行连接配置&指定博客路径 验证 配置 ...

  10. mindxdl---common---db_handler.go

    // Copyright (c) 2021. Huawei Technologies Co., Ltd. All rights reserved.// Package common this file ...