`
ayaoxinchao
  • 浏览: 81014 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

Java函数调用方式——按值传递

阅读更多

Java使用按值传递的函数调用方式,这往往使我感到迷惑。因为在基础数据类型和对象的传递上,我就会纠结于到底是按值传递,还是按引用传递。其实经过学习,Java在任何地方,都一直发挥着按值传递的本色。

 

首先,让我们看一看基础数据类型是如何按值传递的。

 

public static void main(String[] args) {
		
	int a = 2;
	calculate(a);
	System.out.println(a);
	
}

public static void calculate(int param) {
	param += 3;
	System.out.println(param);
}

 输出结果为:

5
2

 这样的结果根据按值传递,并不难理解。

 

 

其次,让我们来看看复杂的对象时如何保持自己的“贞操”,而仅仅是把引用这个“才艺”展示给人们。

 

public static void main(String[] args) {
    // 包装类型,不可变类型	
	Integer b = new Integer(2);
	calculate2(b);
	System.out.println(b);
	
    // 日期类型,目标方法改变对象值,当前日期2013-09-24
	Date d1 = new Date();
	claculate3(d1);
	System.out.println(d1);
		
    // 日期类型,目标方法仅读取对象值,当前日期2013-09-24
	Date d2 = new Date();
	calculate4(d2);
	System.out.println(d2);
}
	
public static void calculate2(Integer param) {
	param += 3;
	System.out.println(param);
}
	
public static void claculate3(Date date) {
	date.setDate(date.getDate() + 1);
	System.out.println(date);
}
	
public static void calculate4(Date date) {
	date = new Date(date.getYear(), date.getMonth(), date.getDate() + 1);
	System.out.println(date);
}

 输出结果为:

5
2
Wed Sep 25 20:24:32 CST 2013
Wed Sep 25 20:24:32 CST 2013
Wed Sep 25 00:00:00 CST 2013
Tue Sep 24 20:24:32 CST 2013

 从结果可以看出:

 

一、包装类型作为不可变的对象,原有的Integer对象并没有改变,所以输出与基础类型的一样。

二、日期类型是可变对象,当仅仅是读取原有对象中的值时,没有问题,调用函数中的打印结果不改变,和当前日期保持一致,只是目标函数中打印的是新对象的值,所以两次打印结果不同;当在目标方法中将原有对象改变,那么两次打印的都是原有对象的值,所以结果相同,并且与初始的new Date()不一样。

 

所以说呢,基础数据类型按值传递很容易理解,但是对于对象,Java也是按值传递,只不过传递的时候不是直接传递对象,而是传递引用的值,引用指向的对象相同而已。

 

以我的水平就能写这么多,希望大牛们觉得不对的地方,给我指出来。。。

1
2
分享到:
评论
6 楼 arthur8 2013-09-25  
JLS上已经明确写了java是值传递~
5 楼 luoyu-ds 2013-09-25  
longshaojian 写道
ayaoxinchao 写道
longshaojian 写道
对于函数调用的参数传递为对象传递时是否可以这样理解:
在方法调用栈上首先创建了一个引用[暂且称其为 StackObject]指向与参数相同的对象地址,这时候区分两个测试方法内部过程可以理解为:

   calculate3 是 改变StackObject 所指向的对象的属性,因为这个所指向的对象与传递到函数的参数对象是同一个,因此改变是受影响的。
   calculate4 是 将 StackReferece 重新指向了一个新的对象地址,从此之后就它就与传递到函数的对象没有关系了,因此改变不会影响到传递的参数对象。

   博主只要在相应的地方打印各个参数和变量对象的内存地址即可一目了然。

   不知道这么理解对不对了~~

仁兄解释的很透彻,和我表达的意思一样,但是我写的太概念化。有机会还是要对JVM深入了解一下,谢谢!


博主的博文也写的很好。其实很凑巧,昨天下午我自己也刚好测试了关于 Integer 包装类型的方法参数传递,结果居然不是意想中的对象值改变,也让我小惊喜了一把,到晚上偶然看到你的博文,大惊咱两居然同一天在测试统一个问题,真是有缘,哈哈。

你俩就搞基吧
4 楼 longshaojian 2013-09-25  
ayaoxinchao 写道
longshaojian 写道
对于函数调用的参数传递为对象传递时是否可以这样理解:
在方法调用栈上首先创建了一个引用[暂且称其为 StackObject]指向与参数相同的对象地址,这时候区分两个测试方法内部过程可以理解为:

   calculate3 是 改变StackObject 所指向的对象的属性,因为这个所指向的对象与传递到函数的参数对象是同一个,因此改变是受影响的。
   calculate4 是 将 StackReferece 重新指向了一个新的对象地址,从此之后就它就与传递到函数的对象没有关系了,因此改变不会影响到传递的参数对象。

   博主只要在相应的地方打印各个参数和变量对象的内存地址即可一目了然。

   不知道这么理解对不对了~~

仁兄解释的很透彻,和我表达的意思一样,但是我写的太概念化。有机会还是要对JVM深入了解一下,谢谢!


博主的博文也写的很好。其实很凑巧,昨天下午我自己也刚好测试了关于 Integer 包装类型的方法参数传递,结果居然不是意想中的对象值改变,也让我小惊喜了一把,到晚上偶然看到你的博文,大惊咱两居然同一天在测试统一个问题,真是有缘,哈哈。
3 楼 ayaoxinchao 2013-09-25  
longshaojian 写道
对于函数调用的参数传递为对象传递时是否可以这样理解:
在方法调用栈上首先创建了一个引用[暂且称其为 StackObject]指向与参数相同的对象地址,这时候区分两个测试方法内部过程可以理解为:

   calculate3 是 改变StackObject 所指向的对象的属性,因为这个所指向的对象与传递到函数的参数对象是同一个,因此改变是受影响的。
   calculate4 是 将 StackReferece 重新指向了一个新的对象地址,从此之后就它就与传递到函数的对象没有关系了,因此改变不会影响到传递的参数对象。

   博主只要在相应的地方打印各个参数和变量对象的内存地址即可一目了然。

   不知道这么理解对不对了~~

仁兄解释的很透彻,和我表达的意思一样,但是我写的太概念化。有机会还是要对JVM深入了解一下,谢谢!
2 楼 longshaojian 2013-09-24  
发现上面的一处纰漏,内存地址不好打印,还是改成 hashcode 吧

添加了 hashcode 的打印之后,就比较明显了



5
2
Wed Sep 25 23:21:31 CST 2013
claculate3 hashCode:	1437989003

Wed Sep 25 23:21:31 CST 2013
d1 hashCode:	1437989003

Wed Sep 25 00:00:00 CST 2013
claculate4 hashCode:	1353898305

Tue Sep 24 23:21:31 CST 2013
d2 hashCode:	1351589027
1 楼 longshaojian 2013-09-24  
对于函数调用的参数传递为对象传递时是否可以这样理解:
在方法调用栈上首先创建了一个引用[暂且称其为 StackObject]指向与参数相同的对象地址,这时候区分两个测试方法内部过程可以理解为:

   calculate3 是 改变StackObject 所指向的对象的属性,因为这个所指向的对象与传递到函数的参数对象是同一个,因此改变是受影响的。
   calculate4 是 将 StackReferece 重新指向了一个新的对象地址,从此之后就它就与传递到函数的对象没有关系了,因此改变不会影响到传递的参数对象。

   博主只要在相应的地方打印各个参数和变量对象的内存地址即可一目了然。

   不知道这么理解对不对了~~

相关推荐

    Java:按值传递还是按引用传递详细解说

    综上所述,在Java中,对于基本数据类型的参数传递实际上是按值传递,而对于对象类型的参数传递则是按引用传递的一种特殊形式——传递的是对象引用的副本,但由于这些副本指向同一个对象,因此对对象的修改会影响到...

    java调用C语言编写的so库中的函数,java调用C语言编写的dll库中的函数

    例如,`java jni调用so中的函数api.txt`中可能包含了具体的JNI函数调用示例。 其次,JNA是一种更高级的接口,它提供了更简洁的方式来调用本地库,无需编写C/C++代码。JNA通过映射Java方法到本地函数,减少了编程...

    参数传递的总结——构造函数

    本文将对"参数传递的总结——构造函数"这一主题进行详细阐述,主要关注如何在构造函数中有效地管理和传递参数。 首先,让我们理解什么是参数传递。在编程中,当我们调用一个函数或方法时,我们可以向其提供一些值,...

    JAVA入门到精通——30天学通JAVA

    学习如何定义和调用方法,理解参数传递机制,以及如何使用返回值,有助于提高代码的可读性和可维护性。 异常处理是Java程序中不可忽视的一部分。通过try-catch-finally语句,你可以捕获并处理可能出现的错误,保证...

    java课程设计实例——java源代码

    7. **方法**:函数的定义与调用,参数传递,方法重载和重写。 8. **异常处理**:理解异常的产生,学习try-catch语句块,以及finally块的使用。 9. **IO流**:学习输入输出流,包括文件操作,字符流与字节流,以及...

    Java语言程序设计——基础篇

    - **方法的定义与调用**:函数(方法)的概念,参数传递方式,返回值类型等。 - **异常处理**:try-catch-finally语句块的使用,自定义异常类的创建。 ### 3. 面向对象编程基础 - **类与对象的概念**:类的定义,...

    java 调用百度人脸对比api接口(csdn)————程序.pdf

    API(Application Programming Interface)是一组预定义的函数、类或协议,允许开发者通过特定方式与软件系统进行交互。在这个例子中,我们关注的是百度的人脸识别服务,它提供了对比和识别人脸的功能。为了使用这些...

    Java调用存储过程--传入集合参数

    ### Java调用存储过程——传入集合参数:深入解析与实践 #### 核心知识点概览 在Java应用中,调用数据库存储过程时,往往需要处理复杂的参数传递,特别是当参数为集合类型时,这一过程变得更加具有挑战性。本文将...

    Java计算机语言函数应用(PDG)

    2. **参数传递**:Java支持两种参数传递方式——按值传递(primitive types)和按引用传递(对象)。按值传递意味着函数接收的是变量的副本,而按引用传递则允许函数修改原始对象的状态。 3. **返回值**:函数可以...

    用JAVA调用Tuxedo服务必须的JAR包

    这就涉及到我们今天要讨论的主题——如何用JAVA调用Tuxedo服务。 首先,我们需要理解的是Java调用Tuxedo服务的基础:Jolt(Java to Tuxedo)。Jolt是一个Java接口,它提供了连接到Tuxedo服务的桥梁,使得Java开发者...

    java多线程案例——未完成

    然后将这个对象传递给`Thread`的构造函数,通过`Thread`来启动线程。 - 实现`Callable`接口:配合`FutureTask`使用,可以返回计算结果并能抛出异常的线程。 2. **线程的生命周期**: - 新建(New):线程对象被...

    函数调用大全.doc

    ### 函数调用大全——JNI调用详解 #### 核心知识点:JNI(Java Native Interface) JNI,即Java Native Interface,是一种允许Java代码调用本地应用程序接口(Native APIs)和库的标准方法,反之亦然。这为Java...

    用java调用科大讯飞的离线语音识别dll实现离线识别

    7. **错误处理和优化**: 处理可能的异常,如DLL加载失败、函数调用错误等。此外,根据实际需求优化性能,例如通过多线程处理多个音频流,或者缓存部分识别结果以减少重复计算。 在提供的压缩包文件中,`路径说明....

    线性规划算法实现——Java版

    线性规划是运筹学中的一种基础优化方法,主要用于解决在一组线性约束条件下,如何最大化或最小化一个线性目标函数的问题。在Java编程环境下,我们可以构建一个线性规划算法来解决这些问题。以下是关于线性规划算法...

    2021Java大厂面试题——大厂真题之蚂蚁金服-Java高级.pdf

    - **寻址方式**:在 JDK 1.8 及以后的版本中,`HashMap` 的寻址方式仅依赖于键(Key)的哈希值来确定元素的存储位置。这减少了冲突的可能性,提高了查询速度。 - **并发问题**:由于 `HashMap` 在 JDK 1.7 和 JDK ...

    JAVA SCRIPT 函数 完整 版

    7. **闭包**:JavaScript的函数能够访问并操作其定义时的作用域,即使在函数调用后,这种特性称为闭包,常用于实现私有变量和模块化。 8. **高阶函数**:接受函数作为参数或者返回函数的函数,例如`map`、`filter`...

    Java直接运行JS代码

    在Java编程环境中,有时我们需要与JavaScript交互,例如执行一些动态脚本...开发者可以轻松地在Java程序中执行JavaScript代码,调用JavaScript函数,甚至传递Java对象到JavaScript环境,从而实现两者之间的协同工作。

Global site tag (gtag.js) - Google Analytics