“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。
在方法调用时,传递的参数,是按值的拷贝传递,方法内改变的是值的拷贝,并不改变原数据。传递的是值的拷贝,也就是说传递后就互不相关了。
指的是在方法调用时,是把对象在内存中的地址值拷贝了一份传给了被调用方(也就是同一个内存空间),所以你更改了同一个内存空间的数据,原数据也会改变。
但是copy这个事情很浪费性能。如果是很复杂的数据,你把整个数据copy一份传过去,非常的耗费性能。所以一般复杂的数据,都使用的引用传递,只是copy了地址值传过去。比如对象,比如数组。
String虽然是对象但是他比较特殊,String类型的变量作为参数时,无论是new出对象,而是直接用字符串赋值,都会像基本类型变量那样以传值方式传递(字符串直接赋值和用new出的对象赋值的区别仅仅在于存储方式不同)。
在这个问答里的解释我觉得很靠谱String类作为参数传递时他的值改变么。该怎样理解?
引用传递和值传递 是不一样的,如果传递的是基本数据类型例如 int ,long boolean 之类的就会改变了,String是特殊的基本类型,本质上是引用类型
String类是final的,而且运用了享元模式,值是不能改变的,但是相同值的多个引用,他们其实在内存中指向的是相同的(这也是java中String对象可以使用==来判断是否相同了),所以很多时候String使用起来很像基本类型,但它确实是面向对象的。
基础介绍完了来回答上面的问题,s传入change函数,因为s本身是不能改变的,在s上自增一个量,实际是将原来的s与要增加的量拼接后赋值给一个新的对象,在内存中是一块全新的,然后将参数中的s指向这块内存。别急~
而String作为参数时,前面也提到String应用了享元模式,传值时,实际传递的是s原来值(引用)的副本,不过这两者都指向一块相同的内存。所以,在第二段中,让s重新指向拼接完成后的值时,并不会改变主函数中s的值。
那么这整个过程,就是定义一个s,内存中分配内存后让s指向它,调用change函数,传入s的副本(另一个引用,不过与正真的s指向相同的内存),在函数体中让这个s的副本重新指向新的内存,并返回他。
以上内容为个人理解,不过不用想得太复杂,只要记住String是对象,但是作为参数是比较特殊,可看作是值传递,而不是引用传递。
这事我是问我们老板的,然后我们老板说,虽然有些数据类型默认是引用传递,但是很多语言里都有关键字,可以更改它的传值类型,比如c++里面的r什么玩意的,括弧,这句我没听懂。从而控制被调用方法不能任意修改原始数据
然后我就说,我一般都是把对象序列化之后传出去,然后再序列化回来,这样去控制两个不是一个对象。老板哭,说居然有这么野鸡的代码
他说序列化非常非常耗费性能,我这代码写得就是垃圾
为了搞明白一个问题,我把短板暴露给老板了
是的,我的Java基础很差,大学唯一挂的科就是JAVA
真不知道我后来为什么要去做开发
附我觉得很有道理的大神解答链接,当当当,跟着测试一遍你就全明白啦(很实在的解答)
理解Java中的引用传递和值传递
String作为方法参数传递 与 引用传递
20190815续更
1、java中控制两个不是一个对象是使用的clone方式,也就是拷贝,其中又分为深拷贝和浅拷贝
2、在c++中的&引用符号(C语言并没有&的概念。引用是C++里面的)
如下图代码中所以,虽然两个方法,都是直接swap(a,b)调用,但是第一种方法,接受的形参,是a和b的引用,这种情况它指代的是实际的对象,在方法体内交换两者数据,main方法体中的元数据a,b是会随之同步更改的。
而方法二,方法里面怎么改数据,原数据都不会变的。
总结:在一般传值调用的机制中只能把实参传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参值发生改变,而实参中的值不会变化。而在引用调用的机制当中是将实参引用的地址传递给了形参,所以任何发生在形参上的改变实际上也发生在实参变量上。
方法一:
void swap(int &p1, int &p2) //此处函数的形参p1, p2都是引用
{ int p; p=p1; p1=p2; p2=p; }
方法二:
void swap(int p1, int p2)
{ int p; p=p1; p1=p2; p2=p; }
主函数
main( )
{
int a,b;
cin>>a>>b; //输入a,b两变量的值
swap(a,b); //直接以变量a和b作为实参调用swap函数
cout<