本篇博客无意讨论Java里面函数传参是否只有值传递还是值传递和引用传递同时存在,仅讨论函数传参的一些原理。

一. 什么是函数传参?

最常见的一个swap函数:下面这个swap函数并不能实现我们想要的交换的功能,因为它传递的是基本数据类型。类似于C++的值传递:二级指针和指针引用函数传参(C++)。这里是Java的函数传参,所以下面将分别介绍两种传参的方式。

public class FunctionTest {

public static void main(String[] args) {

FunctionTest functionTest=new FunctionTest();

int a=11;

int b=22;

functionTest.swap(a,b);

System.out.println(a); //11

System.out.println(b); //22

}

public void swap(int a,int b){

int c=a;

a=b;

b=c;

}

}

二. 基本数据类型(值传递)

public class FunctionTest {

public static void main(String[] args) {

FunctionTest functionTest=new FunctionTest();

int a=11;

int b=22;

functionTest.swap(a,b);

System.out.println(a);

System.out.println(b);

}

public void swap(int c,int d){

int mid=c;

c=d;

d=mid;

}

}

在 functionTest.swap(a,b)调用之前,a,b两个变量如下:

那么在调用functionTest.swap(a,b)之后且未执行int mid=c;之前吶?函数仅完成了函数参数与传入参数的赋值,由于c,d在函数体内重新分配地址,并使用a,b的值进行赋值,在这之后,函数体内对c,d的操作就与a,b无关了。

结论:基本数据类型传入函数参数在函数体内对参数进行的操作不影响原数据

三. 对象数据类型(引用传递)

//和上面代码不同的是int换成了StringBuilder类型,为什么不是String吶?

//因为String类型有着自己的特殊性,这又区别于其它的对象数据类型。

public class FunctionTest {

public static void main(String[] args) {

FunctionTest functionTest=new FunctionTest();

StringBuilder a=new StringBuilder("11");

StringBuilder b=new StringBuilder("22");

functionTest.swap(a,b);

System.out.println(a); //11

System.out.println(b); //22

}

public void swap(StringBuilder c,StringBuilder d){

StringBuilder mid=c;

c=d;

d=mid;

}

}

从输出结果来看,似乎和基本数据类型一样,都没能改变实参a,b的值。引用类型我们依然可以看做是地址的传值,而带有&的则表示地址的值。通过直接引用赋值的方式也不能更改实参的值,这个看起来和上面的基本数据类型是一样的。既然直接更改地址不可行,那么我们可以尝试更改地址指向的值(即上图最后一列的值)。

public class FunctionTest {

public static void main(String[] args) {

FunctionTest functionTest=new FunctionTest();

StringBuilder a=new StringBuilder("11");

StringBuilder b=new StringBuilder("22");

functionTest.swap(a,b);

System.out.println(a); //22

System.out.println(b); //11

}

public void swap(StringBuilder c,StringBuilder d){

StringBuilder mid=new StringBuilder(c);//申请新的内存复制c的值

c.delete(0,c.length());//清空c的值

c.append(d);//将b的值追加在c之后,两句合起来就是d的值赋给c

d.delete(0,d.length());

d.append(mid);

}

}

这次我们通过实参的值更改却是成功了。

结论:对象数据类型传入函数参数在函数体内对参数地址的操作不影响原数据,对地址指向的值更改直接更改了实参的值(毕竟它们指向一个地方)

四. 对象数据类型(引用传递)的一些特例

说是特例,不过是一些对象数据类型在Java语言里面存在着一些特性,如String类型指向的值不可变性,包装类(Integer,Float,Double…),下面就说明一下上面列举的这些例子。

Ⅰ. String类型的值不可变性

package lizi;

public class FunctionTest {

public static void main(String[] args) {

FunctionTest functionTest=new FunctionTest();

String strA="123";

functionTest.test(strA);

System.out.println(strA); //123

}

public void test(String strB){

strB="456";

}

}

上面看似是想通过修改值来更改实参的值,然而却是失败了,这不与引用传参改变地址指向的值可以改变实参的值的结论相违背吗?我们想改变地址指向的值,然而由于String的值不可变,Java并不允许我们直接修改它的值。Java将456存储在一个新申请的地址里面,而原来存在123的地址依然还是123,再将456的地址返回给strB,看似更改地址的值,却被String的特性弄成了修改地址,自然修改完地址与实参的关系也就断了,所以还是符合上面引用传参的结论。

Ⅱ. 包装类的自动装箱

public class FunctionTest {

public static void main(String[] args) {

FunctionTest functionTest=new FunctionTest();

Integer intA=111;

functionTest.test(intA);

System.out.println(intA);//111

}

public void test(Integer intB){

intB=555;

}

}

上面test函数字节码如下:

public void test(java.lang.Integer);

Code:

0: sipush 555

3: invokestatic #14//赋值时调用了valueOf函数进行自动装箱操作

// Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

6: astore_1

7: return

}

由于赋值时候的valueOf函数调用返回了一个Integer对象,变成了和String类似的地址的改变,自然也就无法影响到实参intA的值了。

java 传值为不可变_Java函数传参(String的不可变性)相关推荐

  1. 2021-01-14python函数传参是传值还是传引用? 参数若是简单类型是传值 若是对象类型则是传引用,python是兼容两者传参方式的

    python函数传参是传值还是传引用? 首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题. ...

  2. python函数传值还是地址_python中给函数传参是传值还是传引用

    首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...

  3. C语言与java中函数传参比较

    C语言与java中函数传参比较 首先先说结论:C语言中参数传递有值传递,地址传递,引用传递.但java中的参数传递只有值传递 1.C语言中的参数传递 1>值传递 值传递非常好理解,其实就是对函数 ...

  4. Python基础day05【函数(函数传参的两种形式、函数形参)、拆包、引用、可变与不可变类型、引用做函数参数注意点】

    视频.源码.课件.软件.笔记:超全面Python基础入门教程[十天课程]博客笔记汇总表[黑马程序员]    目录 0.复习 1.函数传参的两种形式[掌握] 2.函数形参 2.1.缺省参数(默认参数) ...

  5. java 不可变性_JAVA不可变类(immutable)机制与String的不可变性(推荐)

    一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String等. 可变类:相对于不可变类, ...

  6. python函数参数传递机制_Python 学习笔记(一) 理解Python的函数传参机制

    对于刚接触Python不久的新手,Python的函数传参机制往往会让人迷惑.学过C的同学都知道函数参数可以传值或者传地址.比如下面这段代码 点击(此处)折叠或打开 void func(int inpu ...

  7. JS一起学05:Date对象、封闭空间、函数传参和封装、获取非行间样式、字符串操作

    一.Date对象 1. 获取 oDate.getFullYear() 获取年份 oDate.getMonth()+1  获取月份 0-11----->1-12 oDate.getDate() 获 ...

  8. C语言 指针在函数传参中的使用

    int add(int a, int b)   //函数传参的时候使用了int整型数据,本身是数值类型.实际调用该函数时,实参将自己拷贝一份,并将拷贝传递给形参进行运算.实参自己实际是不参与运算的.所 ...

  9. 『Python × C++』函数传参机制学习以及对比

    一.Python函数传参 在python中,函数传参实际上传入的是变量的别名,由于python内在的变量机制(名称和变量值相互独立),只要传入的变量不可变(tuple中的元素也要是不可变的才行),那么 ...

最新文章

  1. 人脸识别的“生意经”
  2. 快速小目标检测--Feature-Fused SSD: Fast Detection for Small Objects
  3. 学习:正则表达式的基本语法
  4. hibernate3.4+struts1.3分页封装,有兴趣者可以看一下
  5. 如何在 Flutter 和 Dart 中检查数字字符串
  6. java 资料大全-转
  7. 牛客多校7 - Pointer Analysis(模拟)
  8. Qt工作笔记-Qt奇淫技巧把ToolBar改成标题栏
  9. 项目管理与项目组合管理的不同
  10. js_开发小技巧记录(一)
  11. macOS 安装postman 中文语言包
  12. CogPDF417Tool工具
  13. SAP PP销售预测转独立需求CODE
  14. 图片提取文字很神奇?试试三步实现OCR!
  15. 基于深度学习的SDN家庭网关加密网络流量分类
  16. ASP.NET微信群机器人管家系统,源码分享
  17. 英文卡通字体_40种独特的卡通和漫画字体
  18. CentOS 与 Ubuntu:哪个更适合做服务器
  19. 什么扫地机器人好用,哪一款扫地机器人好?
  20. 网络安全技术-百度百科大全

热门文章

  1. 喜什么颜什么的成语(喜什么颜什么四字成语大全)
  2. 大白话讲解决策树【案例】:如何区分西方人和东方人
  3. Adobe Acrobat XI Pro 2019安装教程
  4. Python人工智能完整学习路线
  5. PTA 7-59 二元一次方程的解
  6. Arduino Mega/Uno制作宏定义键盘(不需刷firmware!!)
  7. 从源码角度上探索AdapterViewFlipper怎么实现广告栏的垂直自动滚动
  8. 程序员如何创新?逆工程师思维
  9. 怎么用dw修改PHP网页模板,【网站模板如何使用】从网站下载的网页模板在dwcs6中如何修改使用?什么是网页设计模板,如何利用网页设计模板?...
  10. 苹果弃妇效应再现:Audience一夜跌去63%(转)