电话:0731-83595998
导航

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

来源: 2017-12-21 11:22

 百度广告

  在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
int x=0;
System.out.println(x);

  void int change(int i){
}

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

  void int change(StringBuffer i){
}
似乎有些奇怪了,两段程序没有特别的不同,可是为什么一个传的是值而另一个传的是引用呢?......

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

  搞清楚这自然是有必要的,不然我也不需要写这么多了,不过的确没有到"非要"的地步。
全局变量是让大家深恶痛绝(又难以割舍)的东西,原因就是使用全局变量要特别注意数据的保护。如果在多线程的程序里使用全局变量简直就等于跟自己过不去。不了解传值和传引用的问题,跟使用全局变量不考虑数据保护的罪过是不相上下下的,甚至有时候比它还要糟。你会莫名其妙,为什么我的返回参数没有起作用,为什么我传进去的参数变成了这样......?
//例3
int x=0;
switchValue(x,y);
System.out.println("y="+y);
void switchValue(int a,int b){

  int c=a;
b=c;
上面是一个交换a,b值的函数,看起来似乎蛮正确的,但是这个函数永远也不会完成你想要的工作。
//例4
StringBuffer b=a;
a=b;
在编程过程中,经常会遇到这种情况,一个变量的值要被临时改变一下,等用完之后再恢复到开始的值。就好像上面的例子,a为了保持它的值,使用b=a做赋值,之后a被改变,再之后a把暂存在b里面的值取回来。这是我们一厢情愿的想法,而事实上,这段代码执行后,你会发现a的值已经改变了。

  Java 提出的思想,在Java里面任何东西都是类。但是Java里面同时还有简单数据类型:int,byte,char,boolean,与这些数据类型相对应的类是Integer,Byte,Character,Boolean,这样做依然不会破坏Java关于任何东西都是类的提法。

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

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

  变量x---->[存放值0]

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

  变量x---->[存放值0]
变量x---->[存放值0]

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

  变量x---->[存放值0]
变量x---->[存放值7]

  说到这里应该已经理解为什么change(x)不能改变x的值了吧?因为这个例子是传值的。
再看例2。
1void method1(){
3 this.change(x);
5
7 i.append(" world!");
例2似乎和例1从代码上看不出什么差别,但是执行结果却是change(x)能改变x的值。依然才从内存的存储角度来看看例2的蹊跷在哪里。

  变量x---->[存放值"Hello"]

  接下来执行第三行change(x),注意,这里就与例1有了本质的不同:调用change(x)时,变量i也指向了x指向的内存空间,而不是指向x的一个拷贝。

  变量x "
[存放值"Hello"]

  于是,第7行对i调用append方法,改变i指向的内存空间的值,x的值也就随之改变了。

  变量x "
[追加为"Hello World!"]

  为什么x值能改变呢?因为这个例子是传引用的。
//例5
str.replaceAll("b","B");
//例6
2 StringBuffer x = new StringBuffer("Hello");
4 System.out.println(x);
6
8 StringBuffer x = new StringBuffer("Hello");
10 System.out.println(x);
12
14 sb.append(" world!");
16
18 sb = new StringBuffer("hi");
20 }
调用method2(),我们认为结果应该是"hi world",因为sb传进来的是引用。可是实际执行的结果是"Hello"!
执行method1()和change1()不用再多说了,上面的例子已经讲解过,这里我们分析一下method2()和change2()。
[存放值"Hello"]

  第9行调用change2,将sb指向x指向的内存空间,也就是传入x的引用。

  变量x "
[存放值"Hello"]

  到这里为止还没有什么异样,接下来执行18行,这里就出现了类似传入值拷贝的变化:new 方法并没有改变sb指向内存的内容,而是在内从中开辟了一块新的空间存放串"hi",同时sb指向了这块空间。

  变量x---->[存放值"Hello"]
变量x---->[另一块存放"hi"的空间]

  接下来再对sb进行append已经和x没有任何关系了。
虽然已经说了这么多,但是感觉传值还是传引用的问题依然没有完全说清楚。因为这个问题本身就是很难归纳总结的问题,所以更多的理解要靠平时的积累和形成。下面几个例子,给大家尝试进行分析。
public static void main(String args) {
int b;
StringBuffer d;
b = a;
d = c;

  a = 2;

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

  //例8,打印结果是什么?

  public static void main(String args) {

  StringBuffer sb = new StringBuffer("Hello ");

  System.out.println("Before change, sb = " + sb);

  changeData(sb);

  System.out.println("After changeData(n), sb = " + sb);

  }

  public static void changeData(StringBuffer strBuf) {

  StringBuffer sb2 = new StringBuffer("Hi ");

  strBuf = sb2;

  sb2.append("World!");

编辑推荐:

下载Word文档

温馨提示:因考试政策、内容不断变化与调整,长理培训网站提供的以上信息仅供参考,如有异议,请考生以权威部门公布的内容为准! (责任编辑:长理培训)

网络课程 新人注册送三重礼

已有 22658 名学员学习以下课程通过考试

网友评论(共0条评论)

请自觉遵守互联网相关政策法规,评论内容只代表网友观点!

最新评论

点击加载更多评论>>

精品课程

更多
10781人学习

免费试听更多

相关推荐
图书更多+
  • 电网书籍
  • 财会书籍
  • 其它工学书籍
拼团课程更多+
  • 电气拼团课程
  • 财会拼团课程
  • 其它工学拼团
热门排行

长理培训客户端 资讯,试题,视频一手掌握

去 App Store 免费下载 iOS 客户端