这个坑,是时候填上了~

一、背景

​  这两天,在网上逛的时候,发现了如下的一道面试题,感觉还有蛮有意思的,要是不仔细看还真容易掉到坑里面。第一眼看起来比较绕,所以比较难理解。最终我跳出了这个坑,也想把这个跳坑的经历分享出来。题目如下 , 请问输出的是什么?为什么?

/**
 * @author hafiz.zhang
 * @description: 一个奇怪的现象
 * @date Created in 2018/7/2 22:44.
 */
public class Test {
    public static void main(String[] args) {
        String ermao = "a";
        String bb = addStr(ermao);
        System.out.println(ermao);
    }

    private static String addStr(String ermao) {
        ermao = ermao + "b";
        return ermao;
    }
}

二、结果及原因

​   毫无疑问,这道题的答案是:a , 你答对了么?在讲解原因之前,让我们想了解一点基础知识吧:

1. 值传递还是引用传递?

​  其实,Java官方并没有给出值传递还是引用传递的概念。官方将Java参数传递类型分为传递基本类型参数和传递引用类型参数。当参数为基本类型(Java八大基本类型:int、short、float、double、long、boolean、byte、char)的时候,就是传递基本类型参数了,当参数为封装类型(非基本类型,如Integer、Long、Boolean等)的时候,就是传递引用传递参数了。官方文档地址:Java参数传递。

2. Java内存模型中的堆和栈

​  从Java的底层机制来说,基本类型的变量存放在栈里;封装类型中,对象放在堆里,对象的引用放在栈里。Java在方法传递参数时,是将变量复制一份,然后传入方法体去执行。

3. 答案是a的原因

因为String类型在传递过程中的步骤如下:

  1. 虚拟机在堆中开辟一块内存,并存值”a”。
  2. 虚拟机在栈中分配给ermao一个内存,内存中存的是1中的堆地址。
  3. 虚拟机复制一份ermao,我们就叫ermao’好了,ermao和ermao’在栈中的内存不同,但此时存的值都是1的堆地址。
  4. 将ermao’传入方法addStr中。
  5. 方法体在堆中开辟一块新内存,并存值”ab”。
  6. 方法体将ermao’的值改变,存入5中新的堆内存地址。
  7. 方法结束,方法外打印ermao,由于ermao存的是1中分配的堆地址,所有打印结果还是”a”。

还不清晰?没关系,那我们直接上个图会不会来得更直观:

4. Java到底有没有引用传递  

  博友:归去来兮辞 说不是传递引用类型就是引用传递,Java中没有引用传递。但其实Java中并没有定义值传递还是引用传递,非基本类型的参数传递就是传递引用类型参数,但String是个特例,String类型对象的值是不可变的,因为String类是通过final修饰的char[]数组来存放结果的。每次为String类型的变量重新赋值实际上都是新建了一个新的String实例,但是方法外部String类型变量没有指向新的String实例,所以也就不会获取到新的更改。这就导致了传递String类型参数时虽然是传递引用类型参数但是无法通过参数传递的方式改变其变量值。欢迎大家提出不同意见来相互讨论学习哈~

三、总结

​  通过本文我们就理解了Java在方法传参的整个过程。其实还是上面那句比较重要的话Java在方法传递参数时,是将变量复制一份,然后传入方法体去执行。给棒棒哒自己一波掌声???,点滴积累,方成大事~

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏牛肉圆粉不加葱

[7] - trait

这是我以前在知乎上看到关于类继承作用的回答,虽不完全正确,却十分明确的表达出了好的代码应避免类继承而尽量使用类组合。Scala 显然也非常赞同这一点,以至于有了...

1082
来自专栏你不就像风一样

Java性能优化之String字符串优化

Java中八大基本数据类型没有String类型,因为String类型是Java对char数组的进一步封装。

2462
来自专栏Android开发指南

6:异常处理

2998
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-day10-基础题-继承;抽象类

Java基础-day10-基础题-继承&抽象类 什么是继承?继承有什么好处? 继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类...

3736
来自专栏农夫安全

python爬虫基础之正则表达式

Python基础前期后后看了五六遍,除了能读懂一些简单的代码,一直也没有进阶。 这次借助一个爬虫教学视频。把学习中的一些重点写下来,一个是自己巩固,一个是也帮助...

4397
来自专栏向治洪

模板方法模式

概述 概念:定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。模板方法模式属于行为类模式。 模板...

2107
来自专栏chenjx85的技术专栏

leetcode-796-Rotate String

2816
来自专栏chenjx85的技术专栏

leetcode-482-License Key Formatting

1463
来自专栏积累沉淀

Python快速学习第三天

第三天: 字典 什么是字典? 字典是Python语言中唯一的映射类型。 映射类型对象里哈希值(键,key)和指向的对象(值,value)是一对多的的关系,通常被...

1958
来自专栏函数式编程语言及工具

泛函编程(5)-数据结构(Functional Data Structures)

     编程即是编制对数据进行运算的过程。特殊的运算必须用特定的数据结构来支持有效运算。如果没有数据结构的支持,我们就只能为每条数据申明一个内存地址了,然后使...

2176

扫码关注云+社区

领取腾讯云代金券