函数调用参数传递类型(java)的用法介绍.

java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清。

(一)基本数据类型:传值,方法不会改变实参的值。

  public class TestFun { 

     public static void testInt(int i){ 

         i=5; 

     } 

     public static void main(String[] args) { 

         int a=0  

         TestFun.testInt(a); 

         System.out.println("a="+a); 

     } 

 }                         

程序执行结果:a=0 。

(二)对象类型参数:传引用,方法体内改变形参引用,不会改变实参的

引用,但有可能改变实参对象的属性值。

举两个例子:

(1)方法体内改变形参引用,但不会改变实参引用,实参值不变。

 public class TestFun2 { 

     public static void testStr(String str){ 

         str="hello";//型参指向字符串 “hello”

     } 

     public static void main(String[] args) { 

         String s="1"

         TestFun2.testStr(s); 

         System.out.println("s="+s); //实参s引用没变,值也不变

     } 

 }                 

执行结果打印:s=1

(2)方法体内,通过引用改变了实际参数对象的内容,注意是“内容”,引用还是不变的。

 import java.util.HashMap; 

 import java.util.Map; 

 public class TestFun3 { 

     public static void testMap(Map map){ 

         map.put("key2","value2");//通过引用,改变了实参的内容

     } 

     public static void main(String[] args) { 

         Map map = new HashMap(); 

         map.put("key1", "value1"); 

         new TestFun3().testMap(map); 

         System.out.println("map size:"+map.size()); //map内容变化了

     } 

 }     

执行结果,打印:map size:2 。可见在方法testMap()内改变了实参的内容。

(3)第二个例子是拿map举例的,还有经常涉及的是StringBuffer :

 public class TestFun4 { 

     public static void testStringBuffer(StringBuffer sb){ 

         sb.append("java");//改变了实参的内容

     } 

     public static void main(String[] args) { 

         StringBuffer sb= new StringBuffer("my "); 

         new TestFun4().testStringBuffer(sb); 

         System.out.println("sb="+sb.toString());//内容变化了

     } 

 } 

执行结果,打印:sb=my java 。

所以比较参数是String和StringBuffer 的两个例子就会理解什么是“改变实参对象内容”了。

总结:

第一:java方法基本数据类型是传值,对象类型传引用,这是千真万确的。

第二:当参数是对象时,无论方法体内进行了何种操作,都不会改变实参 对 对象的引用。

第三:当参数是对象时,只有在方法内部改变了对象的内容时,才会改变实参对象内容。

进一步的思考 
可以看出Java中参数的传递是传递的值,不过这个值有两种,一种是我们看得到的值,也就是primitive类型,比如int,double,char类型的值。另一种就是我们看不到的值,也就是地址值,也可以说是引用值,就是你传递对象或数组类型的参数时传递的值。 
其实我们也可以这么理解,当传参数的时候,会把参数的primitive值或者引用值copy给形式参数。因此,任你在方法里面怎么修改这些值都不会对原来的变量有影响。 
但是对于引用值,如果你在方法里面利用这个引用值访问对象或者数组里面的数据或方法的时候,这和在方法外面直接做事一样的。因为他们持有的是同一个地址。

理解了这些,试想一下,如果在参数前加上final有什么好处吗? 
如果是primitive的参数,有什么用?只能是说你在方法里面不能修改这个变量的值。其实你就算修改了,也只是对方法自己有影响,不会对调用者有影响。 
如果是引用类型的参数呢?又有什么用?不可能说不让你修改对象的值,只能不让你修改这个形式参数变量的引用值。到底有什么好处呢? 
从设计API的角度来说,如果你在primitive参数上加上final,就是告诉自己,这些值对于我的方法来说就是常量,是我需要参考的东西。他们的值在我的整个方法的所有的地方都是一样的。试想,如果不加final,有可能你在方法里面前后两次访问这个变量的值不同,因为你在这之间无意中修改了它。这样就达不到你的意图。 
那么如果是引用类型的参数呢?这里面的意图,就是告诉你在方法里面访问(不论是读还是修改)的这个对象就是传进来的对象,而不是别的。同样保证你在方法里面不同地方的操作都是对这一个对象的操作。

再进一步的思考 
有了前面的思考,我们就可以知道,在设计方法的时候,尽量在参数前面加上final,不管是primitive类型的还是在引用类型的前面。因为这样意图非常简单清楚,在方法里面也可以大胆的引用。回顾你需要修改它们的时候,是不是无意中把他们当成自己定义的临时变量了,这样很危险,容易出乱子。这样是为什么当你用sun的规范做check style的时候他让你改的原因。

还要再来一点思考 
为什么当你调用回调函数的时候必须得加final呢?看了一篇文章说是多线程以及垃圾回收的原因迫使的,我得研究以后再来补充。

Summary: Java中函数参数的传递的更多相关文章

  1. 2013年6月19日星期三java中函数地址值传递

    今天代码审核时确认了一个问题,理解了java中string和stringbuffer赋值问题,看到一个帖子很好,摘录如下: 理解这两个例子需要分清实参和形参的区别,引用和对象的区别 第一个例子的内部执 ...

  2. java中函数是值传递还是引用传递?

    相信有些同学跟我一样,曾经对这个问题很疑惑.在网上也看了一些别人说的观点,评论不一.有说有值传递和引用传递两种,也有说只有值传递的,这里只说下个人见解 先看一个例子 public class Test ...

  3. C语言函数参数的传递详解

    一.三道考题 开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行--唉呀,谁扔我鸡蛋?)考题一,程序代码如下:void Exchg1(int x, int y){   int tmp;    ...

  4. python 函数参数的传递(参数带星号的说明) 元组传递 字典传递

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  5. python中函数参数的引用方式

    值传递和引用传递时C++中的概念,在python中函数参数的传递是变量指向的对象的物理内存地址!!! python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是“传对象引用”的方 ...

  6. python 函数参数的传递(参数带星号的说明)

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  7. python函数参数的传递、带星号参数的传递

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  8. java 中函数的参数传递详细介绍

    java中函数的参数传递 总结: 1.将对象(对象的引用)作为参数传递时传递的是引用(相当于指针).也就是说函数内对参数所做的修改会影响原来的对象.  2.当将基本类型或基本类型的包装集作为参数传递时 ...

  9. Java中到底是值传递还是引用传递?

    Java中到底是值传递还是引用传递? 我们先回顾一下基本概念 实参和形参 参数在编程语言中是执行程序需要的数据,这个数据一般保存在变量中.在Java中定义一个方法时,可以定义一些参数, 举个例子: p ...

随机推荐

  1. Elasticsearch学习之查询去重

    1. 实现查询去重.分页,例如:实现依据qid去重,createTime排序,命令行为: GET /nb_luban_answer/_search { "query": { &qu ...

  2. router之switch

    比较路由中有无switch的区别: 代码一: <Router history={history}> <Route exact path="/" component ...

  3. LeetCode 28 Implement strStr() (实现找子串函数)

    题目链接: https://leetcode.com/problems/implement-strstr/?tab=Description   Problem : 实现找子串的操作:如果没有找到则返回 ...

  4. 使用nginx做反代时遇到413 Request Entity Too Large的解决方法

    在使用nginx做反向代理的时候,被反代的系统在上传文件的时候遇到413 错误 :Request Entity Too Large 原因是nginx限制了上传文件的大小,在nginx中可以配置最大允许 ...

  5. Dokcer制作nginx镜像,提交镜像至仓库

    生成Dockerfile FROM docker.io/hagaico/centos-base-6.5:latest MAINTAINER yatho yatho@163.com ENV DEBIAN ...

  6. C# 队列(Queue)解决简单并发

    日志例子: private static Queue<string> m_Message = new Queue<string>(); private static bool ...

  7. Asp.Net MVC大型项目实践整合 NHibernate与Json序列化

    通过NHibernate我们多表查询是实现了 但由于查询出来的集合中的对象“不是平的”,如何在送到UI绑定成了问题.ExtJs UI组件的数据绑定支持多种格式,如简单数组,Json,Xml.在本项目中 ...

  8. iOS - 指定UIView的某几个角为圆角

    如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore框架).而若要指定某几个角(小于4)为圆角而别的不变时 ...

  9. Python3中关于下划线变量和命名的总结

    变量 #!-*-coding:utf-8-*- #__author__ = 'ecaoyng' # # 变量 #_xxx,单下划线开头的变量,标明是一个受保护(protected)的变量,原则上不允许 ...

  10. 把本地项目文件上传到github远程仓库的教程

    参考廖雪峰的git教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000  非常详 ...