首页 | 资讯动态 | linux基础 | 系统管理 | 网络管理 | 编程开发 | linux数据库 | 服务器技术 | linux相关 | linux认证 | 嵌入式 | 下载中心 | 专题 | linux招聘 | 镜像站
OKLinux中文技术站
·设为首页
·加入收藏
·联系我们
系统管理: 中文环境 系统管理 桌面应用 内核技术 | Linux基础: 基础入门 安装配置 常用命令 经验技巧 软件应用 | Linux数据库: Mysql Postgre Oracle DB2 Sybase other
网络管理: 网络安全 网络应用 Linux服务器 环境配置 黑客安全 | 编程开发: PHP CC++ Python Perl Shell 嵌入式开发 java jsp | PHP技术: PHP基础 PHP技巧 PHP应用 PHP文摘
Linux资讯 Linux招聘 Linux专题 Apache | Linux相关: 硬件相关 Linux解决方案 Linux认证 企业应用 其它Unix | 相关下载: 资料下载 参考手册 开发工具 服务器类 软路由 其它
 技术搜索:
会员中心 注册会员 高级搜索  
  → 当前位置:首页>编程开发>java>Java基础>正文

语言深入:java中究竟是传值还是传引用

http://www.oklinux.cn  2008-01-20  来源: 赛迪网 baocl  会员收藏  游客收藏  【 】 

首先,推荐对Java有一定理解的同仁一本书《Practical Java》。在《Practical Java》中也有一个章节介绍Java中关于传值和传引用的问题,堪称经典。

《Practical Java》

在Java中,事实上底层工作原理不存在传引用的概念,这也象《Practical Java》中所说的那样,Java中只有传值。这句话理解起来需要费一定的周折。

熟悉C的程序员都用过指针,对指针可谓爱之深恨之切。指针是指向一块内存地址的内存数据(有些拗口),也就是说指针本身是一个占用4字节内存的int(32 位系统内),而这个int值恰恰又是另一块内存的地址。比如"hello"这个字串,存放在@0x0000F000这个地址到@0x0000F005这段内存区域内(包括0x00的结束字节)。而在@0x0000FFF0到@0x0000FFF03这四个字节内存放着一个int,这个int的值是 @0x0000F000。这样就形成了一个指向"hello"字串的指针。

在Java中,很多人说没有指针,事实上,在Java更深层次里,到处都是大师封装好的精美绝伦的指针。为了更轻易的讲解Java中关于类和类型的调用,Java中出现了值与引用的说法。浅显的来说,我们可以认为 Java中的引用与C中的指针等效(其实差别非常非常大,但是为了说明我们今天的问题,把他们理解为等效是没有任何问题的)。

所谓传引用的说法是为了更好的讲解调用方式。基于上面对指针的理解,我们不难看出,指针其实也是一个int值,所谓传引用,我们是复制了复制了指针的int值进行传递。为了便于理解,我们可以姑且把指针看作一种数据类型,透明化指针的int特性,从而提出传引用的概念。

重申一遍:Java中只有传值。

1所谓传值和传引用

传值和传引用的问题一直是Java里争论的话题。与C 不同的,Java里面没有指针的概念,Java的设计者巧妙的对指针的操作进行了治理。事实上,在懂C 的Java程序员眼中,Java到处都是精美绝伦的指针。
下面举个简单的例子,说明什么是传值,什么是传引用。
//例1
void method1(){
int x=0;
this.change(x);
System.out.println(x);
}

void int change(int i){
i=1;
}

很显然的,在mothod1中执行了change(x)后,x的值并不会因为change方法中将输入参数赋值为1而变成1,也就是说在执行change(x)后,x的值z依然是0。这是因为x传递给change(int i)的是值。这就是最简单的传值。
同样的,进行一点简单的变化。
//例2
void method1(){
StringBuffer x=new StringBuffer("Hello");
this.change(x);
System.out.println(x);
}

void int change(StringBuffer i){
i.append(" world!");
}
看起来没什么变化,但是这次mothed1中执行了change (x)后,x的值不再是"Hello"了,而是变成了"Hello world!"。这是因为x传递给change(i)的是x的引用。这是最经典的传引用。
似乎有些希奇了,两段程序没有非凡的不同,可是为什么一个传的是值而另一个传的是引用呢?......

2非要搞清楚传值还是传引用的问题吗?

搞清楚这自然是有必要的,不然我也不需要写这么多了,不过的确没有到"非要"的地步。
首先,假如我们不太关心什么是传值什么是传引用,我们一样能写出漂亮的代码,但是这些代码在运行过程中可能会存在着极大的隐患。
全局变量是让大家深恶痛绝(又难以割舍)的东西,原因就是使用全局变量要非凡注重数据的保护。假如在多线程的程序里使用全局变量简直就等于跟自己过不去。不了解传值和传引用的问题,跟使用全局变量不考虑数据保护的罪过是不相上下下的,甚至有时候比它还要糟。你会莫名其妙,为什么我的返回参数没有起作用,为什么我传进去的参数变成了这样......?
一个例子:
//例3
void mothed1(){
int x=0;
int y=1;
switchValue(x,y);
System.out.println("x=" x);
System.out.println("y=" y);
}
void switchValue(int a,int b){

int c=a;
a=b;
b=c;
}
上面是一个交换a,b值的函数,看起来似乎蛮正确的,但是这个函数永远也不会完成你想要的工作。
还有一个例子:
//例4
StringBuffer a=new StringBuffer("I am a ");
StringBuffer b=a;
a.append("after append");
a=b;
System.out.println("a=" a);
在编程过程中,经常会碰到这种情况,一个变量的值要被临时改变一下,等用完之后再恢复到开始的值。就似乎上面的例子,a为了保持它的值,使用b=a做赋值,之后a被改变,再之后a把暂存在b里面的值取回来。这是我们一厢情愿的想法,而事实上,这段代码执行后,你会发现a的值已经改变了。
以上是两个最简单的例子,真正的程序开发过程中,比这要复杂的情况天天都会碰到。

3类型和类

Java 提出的思想,在Java里面任何东西都是类。但是Java里面同时还有简单数据类型:int,byte,char,boolean,与这些数据类型相对应的类是Integer,Byte,Character,Boolean,这样做依然不会破坏Java关于任何东西都是类的提法。
这里提到数据类型和类似乎和我们要说的传值和传引用的问题无关,但这是我们分辨传值和传引用的基础。

4试图分辨传值还是传引用

为什么是"试图分辨"呢?很简单,传值和传引用的问题无处不在,但是似乎还没有人能正统的给出标准,怎样的就是值拷贝调用,怎样的就是引用调用。面对这个问题,我们更多的应该是来自平时积累对Java的理解。
回过头来,我们分析一下上面的几个例子:
先看例1,即使你不明白为什么,但是你应该知道这样做肯定不会改变x的值。为了方便说明,我们给例子都加上行号。
//例1
1 void method1(){
2 int x=0;
3 this.change(x);
4 }
5
6 void int change(int i){
7 i=7;
8}
让我们从内存的存储方式看一下x和I之间到底是什么关系。
在执行到第2行的时候,变量x指向一个存放着int 0的内存地址。

变量x--[存放值0]

执行第3行调用change(x)方法的时候,内存中是这样的情形:x把自己值在内存中复制一份,然后变量i指向这个被复制出来的0。

变量x--[存放值0]
↓进行了一次值复制
变量x--[存放值0]

这时候再执行到第7行的时候,变量i的被赋值为7,而这一步的操作已经跟x没有任何关系了。

共2页: 上一页 1 [2] 下一页

上一篇:进阶-Java编写过程中安全问题解决指南   下一篇:提高写文件的性能的一个比较简单的方法


收藏于收藏夹】 【评论】 【推荐】 【打印】 【关闭
相关文档
·提高写文件的性能的一个比较简单的方法
·进阶-Java编写过程中安全问题解决指南
·J2SE综合介绍:浅谈java程序发布之 jre 篇
·ServletContext与ServletConfig的分析
·深入浅析如何在内部类中返回外部类对象
·J2SE综合--讨论Vector遍历的通用实现
·JSP/Servlet:tomcat深入内部结构描述
·高级:如何在Web工程中实现任务计划调度
·用JSTL标签访问list且判断list的选中项
·JSP/Servlet/JSF:自定义标签的另类体验
·高级:编写多线程Java应用程序常见问题
·J2SE综合--浅析类型转化与final修饰符
·Java多线程设计模式:wait/notify机制
·Java入门--Java入门需掌握的基本概念
·进阶-Java中用动态代理类实现记忆功能
·JAVA高级编程--软件项目质量管理随想
发表评论
密码: 匿名评论
评论内容:

(不超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规)
 
  最新文档
·Java入门:状态对象--数据库的替代者
·Java语言怎样调用外部应用程序
·Java语言深入--关于Java语言的内存泄漏
·JSP/Servlet/JSF:Servlet/JSP配置详解
·进阶-怎样使用AJAX进行WEB应用程序开发
·基础:J2ME程序开发之新手入门九大要点
·Java入门--Java语言接口与继承的本质
·JAVA进阶--如何提升JSP应用程序的效率
·对Java中四种XML解析技术之不完全测试
·编写高级 JScript应用代码
·JSP/Servlet/JSF--对标签库的深入研究
·Java入门--关于字符串分割的两种方法
  阅读排行
·使用AJAX技术实现网页无闪自动局部刷新
·快速教您Apache Tomcat SSL的配置
·Java语言深入--java调用C/C 的过程
·用JSP JavaScript打造二级级联下拉菜单
·JAVA进阶--线程运行栈信息的获取讲解
·J2SE综合--JAVA实现把汉字转化成拼音
·使用WEBWORK实现文件上传方法实例详解
·一个非常有趣的使用spring框架AOP例子
·关于java中相对路径,绝对路径问题总结
·高级:lucene全文检索应用示例及代码简
·详细讲解Struts构架中action的跳转大全
·在Weblogic上配置JMS服务的方法
·Hibernate配置文件中的映射元素详解
·对Java中四种XML解析技术之不完全测试
·基于AJAX的动态树型结构的设计与实现
网摘收藏: