如果你学的第一门程序语言是java可能对这个传递方式没有那么敏感,如果学了c或c++,然后再学java,那么可能对这个问题会感到困惑。

1.值传递与引用传递的概念

在将传递方式之前先理解一下形参与实参。

形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。

实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。

可以这么理解:形参是实参的抽象,实参是调用时的参数,形参是定义函数的参数

值传递:方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。

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

划重点:值传递和引用传递的主要区别

值传递

引用传递

创建副本,在函数体中不能改变原来的值

不创建副本,在在函数体中不能改变原来的值

 创建副本的含义看图:

创建副本也就是说,把要调用的实参先拷贝一份出来,然后用拷贝的那一份传进函数体内。不创建副本时,不会发生copy这个步骤。

举个值传递的栗子:

 public class Test01 {
public static void main(String[] args) {
int a=1,b=2;
swap(a, b);
System.out.println("a="+a);
System.out.println("b="+b);
}
public static void swap(int a,int b) {
int temp=a;
a=b;
b=temp;
}
}

结果:

 a=1
b=2

上面栗子中,在函数中让实现a,b交换,但调用函数后,输出的结果仍然是a,b原来的值,说明函数体中的操作并不能影响a,b在函数体外的值。

引用传递的栗子就不测试了,有兴趣的话可以用c++来测试,参数为定义为别名或指针时,在c++中是引用传递。

误区:传递的参数如果是普通类型,那就是值传递,如果是对象,那就是引用传递。这是错误的!!!!!

2.java中的值传递

在java中,无论参数是基本类型,还是引用数据类型,都是值传递方式。下面来举个引用数据类型的参数,基本数据类型传参的栗子上面已经有了。

 public class Test01 {
public static void swap(Student st1,Student st2) {
Student temp=st1;
st1=st2;
st2=temp;
} public static void main(String[] args) {
Student st1=new Student("张三",20);
Student st2=new Student("李四",20);
swap(st1, st2);
System.out.println("st1:"+st1);
System.out.println("st2:"+st2);
}

结果:

 st1:Student [name=张三, age=20]
st2:Student [name=李四, age=20]

例子中,st1和st2的所指向的对象并没有发生改变。

这时候,你可能会问,既然java是值传递,那么实参会发生拷贝,那拷贝的是什么东西呢?答案是:拷贝的是对象在堆中的地址。来个栗子来验证一下:

 public class Test01 {
public static void print(Student stu1,Student stu2) {
Student temp=stu1;
stu1=stu2;
stu2=temp;
System.out.println("在函数体中交换后打印stu1: "+stu1);
System.out.println("在函数体中交换后打印stu2: "+stu2);
} public static void main(String[] args) {
Student stu1=new Student("stu1",20);
Student stu2=new Student("stu2",30);
print(stu1, stu2);
}
}

结果:

 在函数体中交换后打印stu1:  Student [name=stu2, age=30]
在函数体中交换后打印stu2: Student [name=stu1, age=20]

从结果中可以看出,在函数体中stu1stu2所指向的对象确实是发生了改变,这是因为在值传递的过程中拷贝了他们在堆中的地址。

来看看他们在内存中是怎么样的:

这时候你可能会问,既然java的值传递是拷贝地址,那我能不能改变地址所指向的内容?答案是:当然可以

     public static void  changeInf(Student stu) {
stu.setName("我改名字了");
} public static void main(String[] args) {
Student stu=new Student("张三",18);
changeInf(stu);
System.out.println(stu);
}

结果:

 Student [name=我改名字了, age=18]

对象内容改变了

结论:java中只有值传递,这可能是因为java没有指针和别名引用的原因吧。

为什么说java是只有值传递?的更多相关文章

  1. Java 中的值传递和参数传递

    Java中没有指针,所以也没有引用传递了,仅仅有值传递不过可以通过对象的方式来实现引用传递 类似java没有多继承 但可以用多次implements 接口实现多继承的功能 值传递:方法调用时,实际参数 ...

  2. Java中的值传递和引用传递

    这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...

  3. java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解(勿删)

    head first java里写到“java是通过值传递的,也就是通过拷贝传递”,由此得出结论,方法无法改变调用方传入的参数.该怎么理解呢? 看例子: public class Test1 { pu ...

  4. Java中的值传递

    1.先比较下字符串的比较 == 代表全等于 值和地址(存放地址) 全部相等于. equals 值等于== 和 equals的区别 列如下面的 如果name1==name2是等于的 然而name1==n ...

  5. 为什么说Java中只有值传递

    本文转载自公众号 Hollis 对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文 ...

  6. 一道笔试题来理顺Java中的值传递和引用传递

      题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...

  7. java中的值传递和引用传递有什么区别呀?

    值传递: (形式参数类型是基本数据类型和String):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参 ...

  8. 为什么说Java中只有值传递(转载)

    出处:https://www.hollischuang.com/archives/2275 关于这个问题,在StackOverflow上也引发过广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同, ...

  9. 为什么说Java中只有值传递?

    一.为什么说Java中只有值传递? 对于java中的参数传递方式中是否有引用传递这个话题,很多的人都认为Java中有引用传递,但是我个人的看法是,Java中只有值传递,没有引用传递. 那么关于对象的传 ...

  10. JAVA中只有值传递

    今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这 ...

随机推荐

  1. blast2go本地化 mysql_study

    mysql yum -y install mysql mysqladmin -uroot -passwd "oebiotech" mysql -uroot -poebiotech ...

  2. CitusDB UPSERT

    CitusDB的upsert功能 postgresql9.5 版本支持 "UPSERT" 特性, 这个特性支持 INSERT 语句定义 ON CONFLICT DO UPDATE/ ...

  3. 【模拟】(正解树状数组)-校长的问题-C++-计蒜客

    描述 学校中有 n 名学生,学号分别为 1 - n.再一次考试过后,学校按照学生的分数排了一个名次(分数一样,按照名字的字典序排序).你是一名老师,你明天要和校长汇报这次考试的考试情况,校长询问的方式 ...

  4. VS2010中GetMenu()和GetSubMenu(0)为NULL引发异常的解决方法 及添加方法

    对于前面问题的分析:来源于http://blog.163.com/yuyang_tech/blog/static/216050083201211144120401/ 解决方法1: //来源:http: ...

  5. Hadoop之WritableComprale 排序

    Hadoop之WritableComprale 排序 Hadoop只对key进行排序 排序是 MapReduce 框架中最重要的操作之一.Map Task 和 Reduce Task 均会对数据(按照 ...

  6. mysql 不同版本下 group by 组内排序的差异

    最近发现网上找的 group by 组内排序语句在不同的mysql版本中结果不一样.   建表语句:   SET FOREIGN_KEY_CHECKS=0;   -- ---------------- ...

  7. golang "[]uint8" to string

    关于Uinit8和Byte: The Go Programming Language Specification Numeric types uint8 the set of all unsigned ...

  8. 《Scalable IO in Java》译文

    <Scalable IO in Java> 是java.util.concurrent包的作者,大师Doug Lea关于分析与构建可伸缩的高性能IO服务的一篇经典文章,在文章中Doug L ...

  9. 快速清理maven仓库中下载错误的文件

    有时候使用pom文件下载依赖文件的时候突然网络异常,可能会出现依赖文件出现破损,导致怎么都不能使用,也没有重新下载. 之前解决办法是找到出现破损的文件并删除,让其重新下载,但是这样效率很低,也很难找到 ...

  10. 第三章 JavaScript操作Dom对象

    常用的方法: 1.访问节点: 通过Document.getElementByXXX()获得一个指定节点-->再通过以下属性节点访问节点:第一部分:节点属性a:parentNode 返回节点的父节 ...