- 浏览: 710199 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
javenwong:
你好,我现在需要给一个Composite做圆角处理,不知道怎么 ...
SWT圆角窗口绘制 -
whao189:
回家了详细看看
Storyboard 解析 -
zhaoyubetter:
确实够麻烦
IOS 开发环境,证书和授权文件是什么? -
datawarehouse:
一直对这两个认为是一样的,现在学习了。
Oracle DB中的Schema -
yulanfeiyang:
顶,mark
下载音频,在IOS设备上播放
public class ParamTest { // 初始值为0 protected int num = 0; // 为方法参数重新赋值 public void change(int i) { i = 5; } // 为方法参数重新赋值 public void change(ParamTest t) { ParamTest tmp = new ParamTest(); tmp.num = 9; t = tmp; } // 改变方法参数的值 public void add(int i) { i += 10; } // 改变方法参数属性的值 public void add(ParamTest pt) { pt.num += 20; } public static void main(String[] args) { ParamTest t = new ParamTest(); System.out.println("参数--基本类型"); System.out.println("原有的值:" + t.num); // 为基本类型参数重新赋值 t.change(t.num); System.out.println("赋值之后:" + t.num); // 为引用型参数重新赋值 t.change(t); System.out.println("运算之后:" + t.num); System.out.println(); t = new ParamTest(); System.out.println("参数--引用类型"); System.out.println("原有的值:" + t.num); // 改变基本类型参数的值 t.add(t.num); System.out.println("赋引用后:" + t.num); // 改变引用类型参数所指向对象的属性值 t.add(t); System.out.println("改属性后:" + t.num); } }
这段代码的运行结果如下:
参数--基本类型
原有的值:0
赋值之后:0
运算之后:0
参数--引用类型
原有的值:0
赋引用后:0
改属性后:20
从上面这个直观的结果中我们很容易得出如下结论:
对于基本类型,在方法体内对方法参数进行重新赋值,并不会改变原有变量的值。
对于引用类型,在方法体内对方法参数进行重新赋予引用,并不会改变原有变量所持有的引用。
方法体内对参数进行运算,不影响原有变量的值。
方法体内对参数所指向对象的属性进行运算,将改变原有变量所指向对象的属性值。
上面总结出来的不过是我们所看到的表面现象。那么,为什么会出现这样的现象呢?这就要说到值传递和引用传递的概念了。这个问题向来是颇有争议的。
大家都知道,在JAVA中变量有以下两种:
基本类型变量,包括char、byte、short、int、long、float、double、boolean。
引用类型变量,包括类、接口、数组(基本类型数组和对象数组)。
当基本类型的变量被当作参数传递给方法时,JAVA虚拟机所做的工作是把这个值拷贝了一份,然后把拷贝后的值传递到了方法的内部。因此在上面的例子中,我们回头来看看这个方法:
Java代码
// 为方法参数重新赋值 public void change( int i) { i = 5 ; } Java代码 // 为方法参数重新赋值 public void change(int i) { i = 5; } // 为方法参数重新赋值 public void change(int i) { i = 5; }
在这个方法被调用时,变量i和ParamTest型对象t的属性num具有相同的值,却是两个不同变量。变量i是由JAVA虚拟机创建的作用域在 change(int i)方法内的局部变量,在这个方法执行完毕后,它的生命周期就结束了。在JAVA虚拟机中,它们是以类似如下的方式存储的:
很明显,在基本类型被作为参数传递给方式时,是值传递,在整个过程中根本没有牵扯到引用这个概念。这也是大家所公认的。对于布尔型变量当然也是如此,请看下面的例子:
Java代码
public class BooleanTest { // 布尔型值 boolean bool = true ; // 为布尔型参数重新赋值 public void change( boolean b) { b = false ; } // 对布尔型参数进行运算 public void calculate( boolean b) { b = b && false ; // 为了方便对比,将运算结果输出 System.out.println("b运算后的值:" + b); } public static void main(String[] args) { BooleanTest t = new BooleanTest(); System.out.println("参数--布尔型" ); System.out.println("原有的值:" + t.bool); // 为布尔型参数重新赋值 t.change(t.bool); System.out.println("赋值之后:" + t.bool); // 改变布尔型参数的值 t.calculate(t.bool); System.out.println("运算之后:" + t.bool); } }
Java代码
public class BooleanTest { // 布尔型值 boolean bool = true; // 为布尔型参数重新赋值 public void change(boolean b) { b = false; } // 对布尔型参数进行运算 public void calculate(boolean b) { b = b && false; // 为了方便对比,将运算结果输出 System.out.println("b运算后的值:" + b); } public static void main(String[] args) { BooleanTest t = new BooleanTest(); System.out.println("参数--布尔型"); System.out.println("原有的值:" + t.bool); // 为布尔型参数重新赋值 t.change(t.bool); System.out.println("赋值之后:" + t.bool); // 改变布尔型参数的值 t.calculate(t.bool); System.out.println("运算之后:" + t.bool); } } public class BooleanTest { // 布尔型值 boolean bool = true; // 为布尔型参数重新赋值 public void change(boolean b) { b = false; } // 对布尔型参数进行运算 public void calculate(boolean b) { b = b && false; // 为了方便对比,将运算结果输出 System.out.println("b运算后的值:" + b); } public static void main(String[] args) { BooleanTest t = new BooleanTest(); System.out.println("参数--布尔型"); System.out.println("原有的值:" + t.bool); // 为布尔型参数重新赋值 t.change(t.bool); System.out.println("赋值之后:" + t.bool); // 改变布尔型参数的值 t.calculate(t.bool); System.out.println("运算之后:" + t.bool); } }
输出结果如下:
参数--布尔型
原有的值:true
赋值之后:true
b运算后的值:false
运算之后:true
那么当引用型变量被当作参数传递给方法时JAVA虚拟机又是怎样处理的呢?同样,它会拷贝一份这个变量所持有的引用,然后把它传递给JAVA虚拟机为方法创建的局部变量,从而这两个变量指向了同一个对象。在篇首所举的示例中,ParamTest类型变量t和局部变量pt在JAVA虚拟机中是以如下的方式存储的:
有一种说法是当一个对象或引用类型变量被当作参数传递时,也是值传递,这个值就是对象的引用,因此JAVA中只有值传递,没有引用传递。还有一种说法是引用可以看作是对象的别名,当对象被当作参数传递给方法时,传递的是对象的引用,因此是引用传递。这两种观点各有支持者,但是前一种观点被绝大多数人所接受,其中有《Core Java》一书的作者,以及JAVA的创造者James Gosling,而《Thinking in Java》一书的作者Bruce Eckel则站在了中立的立场上。
我个人认为值传递中的值指的是基本类型的数值,即使对于布尔型,虽然它的表现形式为true和false,但是在栈中,它仍然是以数值形式保存的,即0表示false,其它数值表示true。而引用是我们用来操作对象的工具,它包含了对象在堆中保存地址的信息。即使在被作为参数传递给方法时,实际上传递的是它的拷贝,但那仍是引用。因此,用引用传递来区别与值传递,概念上更加清晰。
最后我们得出如下的结论:
基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。
对象和引用型变量被当作参数传递给方法时,在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。至于到底它是值传递还是引用传递,这并不重要,重要的是我们要清楚当一个引用被作为参数传递给一个方法时,在这个方法体内会发生什么。
发表评论
-
JVM内存管理:深入Java内存区域与OOM
2011-07-12 16:03 909原帖地址:http://icyfenix.iteye.com/ ... -
java面试题~
2010-03-27 14:01 1129一、xml有哪些解析技术 ... -
bat,sh文件执行Java
2009-12-13 21:49 31041.xxx.bat echo using Java %JAV ... -
XML CDATA的作用
2009-11-27 12:40 1559当你用FLASH和xml结合做网站应用程序时,例如你做在我研究 ... -
Transient 关键字用法
2009-11-24 16:49 7961、 java的serialization提供了一个 ... -
serialVersionUID的作用
2009-11-23 12:20 1816serialVersionUID 用来表明类的不同版本间的兼容 ... -
JAVA 注解示例 详解
2009-11-23 12:11 817注解(Annotation) 为我们在代码中天界信息提供了一种 ... -
Log4j使用总结
2009-11-07 11:33 793一、介绍 Log4j是Apache的 ... -
jdom学习:读取xml文件
2009-11-02 12:33 1007<?xml version="1.0" ... -
java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
2009-11-01 23:45 2956在java.io包中还有许多其他的流,主要是为了提高性能和使用 ... -
Java构造函数的调用顺序
2009-09-20 17:19 1638在多级继承的情况下,将从继承树的最上层的父类开始,依次执行各个 ... -
字符串"\"替换问题
2009-08-04 15:44 829String s = "F:\\das\\src\\ ... -
java的volatile是什么意思
2009-08-03 10:01 1482我们知道,在Java中 ... -
数组和容器的排序
2009-06-23 18:11 1000排序方法一: package Stuty_Array; ... -
小常识
2009-06-19 10:48 8181. JVM 中, 线程持有Stack, Stack随线程创建 ... -
计算两个日期之间相差的月数
2009-05-27 00:18 1607/** * 计算两个日期之间相差的月数 ... -
在JAVA中读取文件乱码的解决办法
2009-05-20 13:54 1286public static String encodin = ... -
保存Java程序状态及设置Properties文件
2009-05-18 16:11 1028使用Properties文件来保存.Properties文件的 ... -
JavaBeans的属性
2009-05-04 15:41 910JavaBeans的属性与一般Java程序中所指的属性,或者说 ... -
String 的contains方法
2009-03-10 16:55 1002当且仅当此字符串包含指定的值时,返回 true。
相关推荐
Java参数传递的规则是:**Java只使用值传递,但这种值传递对于对象参数表现为类似引用传递的行为。** 在值传递中,函数或方法接收的是原始数据类型(如int、double、boolean)参数的副本。例如,如果有一个方法...
### JNI中C和Java参数传递详解 #### 一、引言 Java Native Interface (JNI) 是Java平台标准的一部分,用于让Java代码与其他语言写的代码进行交互。本文将深入探讨在JNI环境中,C/C++和Java之间如何进行参数传递,...
在计算机编程领域,特别是对于面向对象语言如Java而言,“传值”与“传引用”的概念是理解数据传递机制的关键所在。Java作为一种广泛使用的高级编程语言,在设计之初就考虑到了如何避免C/C++等语言中的复杂性,特别...
值传递和引用传递是Java中参数传递的两种方式。在`Demo03`中,展示了值传递的例子。当传递基本类型如`int`时,实际传递的是变量的副本,对副本的修改不会影响原始变量。因此,`change(a)`方法内部对`a`的改变不会...
JMS(Java Message Service)API是Java中处理消息传递的标准接口,常用于实现异步通信和解耦系统组件。消息队列(Message Queue)如ActiveMQ、RabbitMQ等,可以缓存消息并确保其可靠传输。JMX(Java Management ...
要理解这个错误,我们需要回顾Java的数据类型系统。Java有两类数据类型:原始类型(如int、char、boolean等)和引用类型(如类、接口和数组)。`setAttribute`方法只接受引用类型的值,因此需要将原始类型转换为它的...
- Java 支持参数传递,即传值调用。 - 方法可以返回单一值或复杂类型(如数组、列表)。 - **封装**: - 通过 setter 和 getter 方法提供对实例变量的安全访问。 - 这种做法提高了程序的稳定性和可维护性。 ###...
- **Java语言的产生**:回顾Java的历史背景和发展历程。 - **Java语言的发展**:讲述Java从最初的版本到现在的演变过程。 - **Java语言的关键特点**:详细介绍Java的面向对象、简单高效、与平台无关等核心特点。 ...
14.2.3 回顾Java Beans 14.3 堵塞 14.3.1 为何会堵塞 14.3.2 死锁 14.4 优先级 14.4.1 线程组 14.5 回顾runnable 14.5.1 过多的线程 14.6 总结 14.7 练习 第15章 网络编程 15.1 机器的标识 15.1.1 服务器和客户机 ...
14.2.3 回顾Java Beans 14.3 堵塞 14.3.1 为何会堵塞 14.3.2 死锁 14.4 优先级 14.4.1 线程组 14.5 回顾runnable 14.5.1 过多的线程 14.6 总结 14.7 练习 第15章 网络编程 15.1 机器的标识 15.1.1 服务器和客户机 ...
在Java编程语言中,`i=i++`是一个典型的自增表达式...这种行为的根源在于Java的按值传递以及自增操作的顺序规则。为了防止这种意外,最好避免在Java中使用这样的复合赋值操作,特别是在需要依赖自增顺序的复杂逻辑中。
- **Java简史**:回顾Java的发展历程。 - **Java的应用场景**:探讨Java在不同领域的实际应用案例,如Food Network、NASA等。 - **商业应用**:讲解Java在企业级应用中的角色。 - **开源社区**:介绍SourceForge等...
14.2.3 回顾Java Beans 14.3 堵塞 14.3.1 为何会堵塞 14.3.2 死锁 14.4 优先级 14.4.1 线程组 14.5 回顾runnable 14.5.1 过多的线程 14.6 总结 14.7 练习 第15章 网络编程 15.1 机器的标识 15.1.1 服务器和客户机 ...
12.2.1 按值传递 12.2.2 克隆对象 12.2.3 使类具有克隆能力 12.2.4 成功的克隆 12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更...
Java EE,全称为Java Platform, Enterprise Edition,是Java平台针对企业级应用开发的版本。它提供了丰富的API和服务,用于构建分布式、多层架构的应用程序,包括Web服务、数据库连接、事务处理、安全性和多语言支持...
在描述中提到,作者推荐这本书而非观看视频教程,暗示了书籍可能更便于读者按照自己的节奏学习,并能随时回顾查阅。 Java开发是软件行业中非常重要的一个领域,Java作为一种多用途、跨平台的编程语言,广泛应用于...
8.3 命名习惯大回顾 204 8.4 Java中的注释 205 8.4.1 使用双斜杠的单行注释 205 8.4.2 多行注释 206 8.4.3 Javadoc注释 206 8.5 小结:包让Java的类更清晰优雅 208 8.6 习题 209 第9章 再看数组、字符串和...
- **方法和消息传递**:探讨Java中方法调用和消息传递的机制。 - **终结器**:解释终结器(finalizer)的概念及其在资源释放中的作用。 - **子类**:讨论子类继承父类特性的过程及其应用场景。 - **Java语言接口**:...
14.2.3 回顾Java Beans 14.3 堵塞 14.3.1 为何会堵塞 14.3.2 死锁 14.4 优先级 14.4.1 线程组 14.5 回顾runnable 14.5.1 过多的线程 14.6 总结 14.7 练习 第15章 网络编程 15.1 机器的标识 15.1.1 服务器和客户机 ...