声明:本博客为原创博客,未经同意。不得转载!

原文链接为http://blog.csdn.net/bettarwang/article/details/30989755

我们都知道。在Java中,除了基本数据类型之外,其它的都是引用类型,当它们作为函数參数时,传递的也是引用。通过引用能够改变对象的值,非常多人便因此而忽略形參与实參,引用与对象的关系问题。废话不多说,先看以下一个样例:

  1. import java.util.*;
  2.  
  3. public class Student
  4. {
  5. private String name;
  6. private int age;
  7. public Student(String name,int age)
  8. {
  9. this.name=name;
  10. this.age=age;
  11. }
  12. public void printInfo()
  13. {
  14. System.out.println("Name:"+name+" age:"+age);
  15. }
  16.  
  17. public static void change(Student student)
  18. {
  19. Student stu=new Student("Lucy",26);
  20. student=stu;
  21. student.printInfo();
  22. }
  23. public static void main(String[]args)
  24. {
  25. Student s=new Student("Lily",25);
  26. s.printInfo();
  27. change(s);
  28. s.printInfo();
  29. }
  30. }

执行结果例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQmV0dGFyd2FuZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

显然,形參改变了。可是实參没有被改变,这是为什么呢?

要分析这个问题。首先要分清Java中的引用与对象的关系,比方此处s是引用,它存储在栈中,而它指向的对象存储在堆中,所以当使用change函数时。实际上仅仅进行了下面操作:首先是将实參的值传给形參,即形參student也指向s所指向的对象;之后让student指向change函数中新建的对象。也就是说,在这个函数中,实參仅仅是在一開始起了一下作用,后面便再也没它的事儿了。我们添加一个输出操作就可以印证上面的结论。新代码例如以下:

  1. import java.util.*;
  2.  
  3. public class Student
  4. {
  5. private String name;
  6. private int age;
  7. public Student(String name,int age)
  8. {
  9. this.name=name;
  10. this.age=age;
  11. }
  12. public void printInfo()
  13. {
  14. System.out.println("Name:"+name+" age:"+age);
  15. }
  16.  
  17. public static void change(Student student)
  18. {
  19. //新增的输出操作
  20. if(student!=null)
  21. {
  22. student.printInfo();
  23. }
  24. Student stu=new Student("Lucy",26);
  25. student=stu;
  26. student.printInfo();
  27. }
  28. public static void main(String[]args)
  29. {
  30. Student s=new Student("Lily",25);
  31. s.printInfo();
  32. change(s);
  33. s.printInfo();
  34. }
  35. }

输出结果例如以下:



由输出结果可知确实是实參仅仅起了一次结合的作用,而在整个函数中实參s及其指向的对象都未被改变,所以显然change函数达不到对应的预期。实际上,要实现改变对象的目的,应该像以下这样写:

  1. import java.util.*;
  2.  
  3. public class Student
  4. {
  5. private String name;
  6. private int age;
  7. public Student(String name,int age)
  8. {
  9. this.name=name;
  10. this.age=age;
  11. }
  12. public void printInfo()
  13. {
  14. System.out.println("Name:"+name+" age:"+age);
  15. }
  16. public void setName(String name)
  17. {
  18. this.name=name;
  19. }
  20. public void setAge(int age)
  21. {
  22. this.age=age;
  23. }
  24. public static void change(Student student)
  25. {
  26. student.setName("Lucy");
  27. student.setAge(26);
  28. }
  29. public static void main(String[]args)
  30. {
  31. Student s=new Student("Lily",25);
  32. s.printInfo();
  33. change(s);
  34. s.printInfo();
  35. }
  36. }

输出结果例如以下:



显然,这个change函数达到了我们的预期,原因就在于它是真正地改变了对象的属性。

通过上面这个样例可知。尽管Java中传递的是引用,能够轻易地实现对对象的改变。可是仍然要注意形參与实參、引用与对象的关系。千万不要简单地以为传引用就一定能够实现对象的改变。否则可能犯下低级错误。

深刻理解Java中形參与实參,引用与对象的关系的更多相关文章

  1. 深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因

    声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/det ...

  2. 深刻理解Java中的String、StringBuffer和StringBuilder的差别

    声明:本博客为原创博客,未经同意.不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(链接为http://blog.csdn.net/bettarwang/article/detai ...

  3. JDK学习---深入理解java中的HashMap、HashSet底层实现

    本文参考资料: 1.<大话数据结构> 2.http://www.cnblogs.com/dassmeta/p/5338955.html 3.http://www.cnblogs.com/d ...

  4. 理解Java中的弱引用(Weak Reference)

    本篇文章尝试从What.Why.How这三个角度来探索Java中的弱引用,理解Java中弱引用的定义.基本使用场景和使用方法.由于个人水平有限,叙述中难免存在不准确或是不清晰的地方,希望大家可以指出, ...

  5. [译]线程生命周期-理解Java中的线程状态

    线程生命周期-理解Java中的线程状态 在多线程编程环境下,理解线程生命周期和线程状态非常重要. 在上一篇教程中,我们已经学习了如何创建java线程:实现Runnable接口或者成为Thread的子类 ...

  6. 深入理解Java中的不可变对象

    深入理解Java中的不可变对象 不可变对象想必大部分朋友都不陌生,大家在平时写代码的过程中100%会使用到不可变对象,比如最常见的String对象.包装器对象等,那么到底为何Java语言要这么设计,真 ...

  7. 深入理解Java中的IO

    深入理解Java中的IO 引言:     对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务 < Thinking in Java >   本文的目录视图如下: ...

  8. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

  9. 理解Java中的ThreadLocal

    提到ThreadLocal,有些Android或者Java程序员可能有所陌生,可能会提出种种问题,它是做什么的,是不是和线程有关,怎么使用呢?等等问题,本文将总结一下我对ThreadLocal的理解和 ...

随机推荐

  1. SQL Prompt 格式化SQL会自动插入分号的问题

    一.问题 安装新版SQL Prompt,格式化SQL都会自动在SQL末端插入分号 格式化前 格式化后 二.解决方法 选择SQL Prompt下的Options... 选择左侧的Format下Style ...

  2. Sphinx排序模式

    目前SPHINX支持6种排序模式.分别是: 1. SPH_SORT_RELEVANCE2. SPH_SORT_ATTR_DESC3. SPH_SORT_ATTR_ASC4. SPH_SORT_TIME ...

  3. EPT和VPID简介

    EPT(Extended Page Tables,扩展页表),属于Intel的第二代硬件虚拟化技术,它是针对内存管理单元(MMU)的虚拟化扩展.EPT降低了内存虚拟化的难度(与影子页表相比),也提升了 ...

  4. 导出csv文件(php实现)

    <?php namespace App\Library\lib; class CsvLib { /** * [构造函数] * */ public function __construct() { ...

  5. 条款14:在资源管理类中心copying行为(Think carefully about copying behavior in resource-manage classes)

    NOTE: 1.复制RAII 对象必须一并赋值它所管理的资源,所以资源的copying行为决定RAII对象的copying行为. 2.普遍而常见的RAII class copying 行为是: 抑制c ...

  6. python基础知识04-散列类型运算优先级和逻辑运算

    散列类型 1.集合 定义集合 se = {1,2,3,4} se = set()定义空集合 se = {1,3,5,7} se2 = {1,3,8,9} se & se2 {1,3} 交集 s ...

  7. LeetCode(52) N-Queens II

    题目 Follow up for N-Queens problem. Now, instead outputting board configurations, return the total nu ...

  8. 【HIHOCODER 1044】题目1 : 状态压缩·一

    描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市--那座城市即将举行美食节! 但是不幸的是,小Hi和小Ho并没有能够买到很好的火车票-- ...

  9. Vue微信自定义分享时安卓系统config:ok,ios系统config:invalid signature签名错误,或者安卓和ios二次分享时均config:ok但是分享无效的解决办法

    简述需求:要求指定页面可以进行微信自定义分享(自定义标题,描述,图片,链接),剩下的页面隐藏所有基础接口.二次分享依然可以正常使用,切换至其他页面也可以正常进行自定义分享. 这两天在做微信自定义分享的 ...

  10. webservice学习第一天

    Webservice Webservice就是一种远程调用技术,他的作用就是从远程系统中获取业务数据 1 课程安排 l 什么是webservice l Webservice入门程序 l Webserv ...