- 浏览: 34927 次
- 性别:
- 来自: 大连
-
最新评论
-
qufulin:
活用ajax,如何发送异步请求我就不给你说了, 我这给你贴段使 ...
如何通过代码实现查看网页源程序 -
Komes:
zhangdaiping 写道啥也不说了,上个图给楼主看。
先 ...
如何通过代码实现查看网页源程序 -
zhangdaiping:
啥也不说了,上个图给楼主看。
如何通过代码实现查看网页源程序 -
iamsk:
做个记号,赞
到底传值还是传引用 -
yuankai:
我也说一个吧。在写Blog的时候,如果有附件,而且附件比较大的 ...
javaeye让人多少有些不爽的bug们
好东西分享
JAVA中的传递都是值传递吗?有没有引用传递呢?
在回答这两个问题前,让我们首先来看一段代码:
- 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);
- }
- }
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虚拟机所做的工作是把这个值拷贝了一份,然后把拷贝后的值传递到了方法的内部。因此在上面的例子中,我们回头来看看这个方法:
// 为方法参数重新赋值 public void change(int i) { i = 5; }
在这个方法被调用时,变量i和ParamTest型对象t的属性num具有相同的值,却是两个不同变量。变量i是由JAVA虚拟机创建的作用域在change(int i)方法内的局部变量,在这个方法执行完毕后,它的生命周期就结束了。在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。而引用是我们用来操作对象的工具,它包含了对象在堆中保存地址的信息。即使在被作为参数传递给方法时,实际上传递的是它的拷贝,但那仍是引用。因此,用引用传递来区别与值传递,概念上更加清晰。
最后我们得出如下的结论:
- 基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。
- 对象和引用型变量被当作参数传递给方法时,在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。至于到底它是值传递还是引用传递,这并不重要,重要的是我们要清楚当一个引用被作为参数传递给一个方法时,在这个方法体内会发生什么。
向原作者致敬,转自:
作者:臧圩人(zangweiren)
网址:http://zangweiren.iteye.com
发表评论
-
dom4j操作xml基础
2010-09-15 21:38 908DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准 ... -
手工搭建SSH集成工程
2010-09-15 21:23 860//搭建SSH集成工程://1.建立普通web工程,导入SSH ... -
tomcat+eclipse工程发布的两种方式
2010-09-15 20:52 2154tomcat+eclipse工程发布的 ... -
优秀的Java程序员必须了解GC的工作原理(转)
2010-05-05 20:14 1040一个优秀的Java程序 ... -
详细解析Java中抽象类和接口的区别(转)
2010-05-05 20:11 690在Java语言中, abs ... -
Vector、ArrayList和List的异同(转)
2010-05-05 20:07 1101线性表,链表,哈希表 ... -
JAVA面试题解惑系列(十一)——这些运算符你是否还记得?
2010-05-01 00:13 694好东西分享 有些运算符在JAVA语言中存在着,但是在实际开发 ... -
JAVA面试题解惑系列(十)——话说多线程
2010-05-01 00:11 752好东西分享 线程或者说多线程,是我们处理多任务的强大工具。线 ... -
JAVA面试题解惑系列(九)——继承、多态、重载和重写
2010-05-01 00:09 727好东西分享 什么是多 ... -
JAVA面试题解惑系列(八)——聊聊基本类型(内置类型)
2010-05-01 00:08 805好东西分享 基本类型,或者叫做内置类型,是JAVA中不同于类 ... -
JAVA面试题解惑系列(七)——日期和时间的处理
2010-05-01 00:06 810好东西分享 日期和时间的处理不仅在面试题中会考到,在实际项目 ... -
JAVA面试题解惑系列(六)——字符串(String)杂谈
2010-05-01 00:04 718好东西分享上一次我们已经一起回顾了面试题中常考的到底创建了几个 ... -
JAVA面试题解惑系列(四)——final、finally和finalize的区别
2010-05-01 00:00 688好东西分享final、finally和finalize的区别是 ... -
JAVA面试题解惑系列(三)——变量(属性)的覆盖
2010-04-30 23:58 586好东西分享我们来看看这么一道题: Java代码 ... -
JAVA面试题解惑系列(二)——到底创建了几个String对象?
2010-04-30 23:56 758好东西分享 我们首先来看一段代码: Java代码 ... -
JAVA面试题解惑系列(一)——类的初始化顺序
2010-04-30 23:54 694好东西分享大家在去参加面试的时候,经常会遇到这样的考题:给你两 ... -
关于import org.apache.xpath.XPathAPI;
2009-06-23 12:31 4034import org.apache.xpath.XPathAP ... -
到底传值还是传引用
2009-06-10 10:32 1019不少同学总是质疑java编程中参数的传递,到底是传 ... -
自学Java 之 组合键
2009-06-09 10:10 1598今天练习了一个小的聊天程序,实现客户端与服务器端相 ... -
Socket 异常 Connection refused 解决办法
2009-06-02 17:57 5702今天练习Socket编程,在new Socket时无意 ...
相关推荐
.22 1.5 JAVA面试题解惑系列(五)——传了值还是传了引用? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31 1.6 JAVA面试题解惑系列(六)——字符串(String)杂谈 . . . . . . . . . ....
**1.5 JAVA面试题解惑系列(五)——传了值还是传了引用?** - **知识点**:澄清Java中参数传递的机制,即所有参数都是按值传递,但对于对象而言,传递的是指向该对象的引用的值,而非对象本身。 **1.6 JAVA面试题...
总结来说,对于Java面试中常出现的关于类初始化顺序的问题,开发者应当掌握以下几点: 1. 单个类内成员的初始化顺序:静态变量、静态初始化块、变量、初始化块、构造器。 2. 在继承关系中,子类的静态成员会在父类...
### Java面试题解惑系列——知识点详解 #### 1. 类的初始化顺序 在Java中,类的初始化顺序是一个常见的面试考察点。当一个类被加载时,Java虚拟机(JVM)会按照一定的顺序执行类中的不同部分,包括静态变量、静态...
JAVA面试题解惑系列(一)——类的初始化顺序 JAVA 是一门面向对象的编程语言,类的初始化顺序是 JAVA 程序员和 JAVA 工程师面试中一个非常重要的知识点。本文将详细讲解类的初始化顺序,并提供了相关的测试代码,...
JAVA 面试题解惑系列之 String 对象创建机制 本文将深入探讨 JAVA 中 String 对象的创建机制,解答常见的面试题目,并探索 String 对象池的概念和机制。 一、String 对象的创建方式 在 JAVA 中,String 对象可以...
《JAVA面试题解惑系列——类的初始化顺序》 在Java编程中,理解类的初始化顺序是面试中常见的考察点,因为它直接关系到程序的执行逻辑。本文将深入探讨类的初始化过程,以及在继承场景下如何理解这个过程。 首先,...
【标题】:“面试题解惑系列(十)——话说多线程” 【描述】:本篇文章主要探讨的是Java中的多线程概念及其在面试中常见的问题解析。 【标签】:“面试题解惑系列(十)——话说多线程” 【部分内容】:在Java中,多...
JAVA面试题解惑系列(一)——类的初始化顺序 在Java编程语言中,理解类的初始化顺序是非常重要的,尤其是在涉及继承的情况下。本节将详细介绍类初始化的规则,并通过实例来帮助理解。 ##### 类的初始化顺序规则 ...
“JAVA面试题解惑系列(八)——聊聊基本类型(内置类型)”涵盖了Java的原始数据类型,包括int、char、boolean等,它们与引用类型的不同之处以及它们的默认值和范围。 “JAVA面试题解惑系列(九)——继承、多态、...
### Java面试题解惑系列——类的初始化顺序详解 #### 背景介绍 在Java面试过程中,关于类的初始化顺序的问题是常见的考察点之一。此类问题通常涉及到类的加载机制、静态变量与实例变量的区别、初始化块的作用及执行...
尤其对于那些准备应对技术面试的Java程序员和工程师来说,掌握这一知识点是面试时的必备能力之一。本文将深入探讨Java中类的初始化顺序,特别是在有继承关系的情况下,各个初始化阶段的执行流程,以及这一顺序的重要...
### JAVA面试题解惑系列知识点总结 #### 一、类的初始化顺序 **知识点概述:** 在Java中,类的初始化顺序是一个常见的面试问题。它主要涉及到类成员(包括静态和非静态)的加载和初始化过程。理解这些基础知识有助...
Java中的字符串(String)是编程面试中的热门话题,其特性与操作是面试官常常用来考察候选人基础知识的手段。本文将深入探讨String对象的一些关键知识点。 首先,我们要了解`String`类的`length()`方法。这个方法返回...
《JAVA面试题解惑系列——类的初始化顺序》 在Java面试中,关于类的初始化顺序是一个常见的考点。深入理解这一概念,对于成为一名合格的Java开发者至关重要。在Java中,类的初始化顺序遵循一定的规则,这包括静态...
### JAVA面试题解惑系列——类的初始化顺序 #### 一、基础知识回顾 在Java编程中,类的初始化顺序是一个非常重要的概念,特别是在面试时,它经常被用来考察面试者对于Java类加载机制的理解程度。类的初始化顺序...
JAVA面试题解惑系列.pdf Java面试题(基础).pdf JVM 实用参数系列 - v1.0.pdf JVM与性能优化知识点整理.pdf JVM面试专题.docx JVM面试专题及答案.pdf Linux系统Redis笔记.docx MongoDB学习笔记.docx mybatis原理....
- **杨中科微软面试分享**:通过一位成功通过微软面试的同学的经历,分享了面试准备的方法和技巧。 - **我的求职经历(原创)**:讲述了作者自己求职过程中的心路历程,为即将毕业的学生提供了宝贵的参考意见。 - **...