Java只有按值传递,但是看见一些人反复讨论这个问题,不禁要问一下为什么?1、说“按引用传递”的人也是经过思考的,是不是他们使用了不同的术语,或者他们的术语不同于我们的术语?
2、说“按引用传递”的人,有哪些典型人物?
我知道的有TIJ,忘记第几版了,最新版改了没有,知道的说一下。
还有CSDN上的一篇《java按值传递还是按引用传递详细解说》
有没有正规教材上说“按引用传递”的?
3、C语言也讨论“按引用传递”这个问题吗?
4、为什么“按引用传递”是错误的?[不要讨论它错误之处,而是问一问他们的思路为什么错误】?

解决方案 »

  1.   

    这个在Java里面是经常被提起的问题,也有一些争论,似乎最后还有一个所谓的结论:“在Java里面参数传递都是按值传递”。事实上,这很容易让人迷惑,下面先分别看看什么是按值传递,什么是按引用传递,只要能正确理解,至于称作按什么传递就不是个大问题了。 
    1:按值传递是什么 
    指的是在方法调用时,传递的参数是按值的拷贝传递。示例如下: 
    public class TempTest { 
    private void test1(int a){ 
    //做点事情 

    public static void main(String[] args) { 
    TempTest t = new TempTest(); 
    int a = 3; 
    t.test1(a);//这里传递的参数a就是按值传递 


    按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。 
    示例如下: 
    public class TempTest { 
    private void test1(int a){ 
    a = 5; 
    System.out.println("test1方法中的a==="+a); 

    public static void main(String[] args) { 
    TempTest t = new TempTest(); 
    int a = 3; 
    t.test1(a);//传递后,test1方法对变量值的改变不影响这里的a 
    System.out.println(”main方法中的a===”+a); 


    运行结果是: 
    test1方法中的a===5 
    main方法中的a===3 2:按引用传递是什么 
    指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。 
    示例如下: 
    public class TempTest { 
    private void test1(A a){ } 
    public static void main(String[] args) { 
    TempTest t = new TempTest(); 
    A a = new A(); 
    t.test1(a); //这里传递的参数a就是按引用传递 


    class A{ 
    public int age = 0; 
    } 3:按引用传递的重要特点 
    传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。 
    示例如下: 
    第1行 public class TempTest { 
    第2行 private void test1(A a){ 
    第3行 a.age = 20; 
    第4行 System.out.println("test1方法中的age="+a.age); 
    第5行 } 
    第6行 public static void main(String[] args) { 
    第7行 TempTest t = new TempTest(); 
    第8行 A a = new A(); 
    第9行 a.age = 10; 
    第10行 t.test1(a); 
    第11行 System.out.println(”main方法中的age=”+a.age); 
    第12行 } 
    第13行 } 
    第14行 class A{ 
    第15行 public int age = 0; 
    第16行 } 
    运行结果如下: 
    test1方法中的age=20 
    main方法中的age=20 4:理解按引用传递的过程——内存分配示意图 
    要想正确理解按引用传递的过程,就必须学会理解内存分配的过程,内存分配示意图可以辅助我们去理解这个过程。 
    用上面的例子来进行分析: 
    (1):运行开始,运行第8行,创建了一个A的实例,内存分配示意如下: 
    (2):运行第9行,是修改A实例里面的age的值,运行后内存分配示意如下: 
    (3):运行第10行,是把main方法中的变量a所引用的内存空间地址,按引用传递给test1方法中的a变量。请注意:这两个a变量是完全不同的,不要被名称相同所蒙蔽。 内存分配示意如下: 
    由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图如下: 
    也就是说:是两个变量都指向同一个空间。 (4):运行第3行,为test1方法中的变量a指向的A实例的age进行赋值,完成后形成的新的内存示意图如下: 
    此时A实例的age值的变化是由test1方法引起的 (5):运行第4行,根据此时的内存示意图,输出test1方法中的age=20 
    (6):运行第11行,根据此时的内存示意图,输出main方法中的age=20 5:对上述例子的改变 
    理解了上面的例子,可能有人会问,那么能不能让按照引用传递的值,相互不影响呢?就是test1方法里面的修改不影响到main方法里面呢? 
    方法是在test1方法里面新new一个实例就可以了。改变成下面的例子,其中第3行为新加的: 
    第1行 public class TempTest { 
    第2行 private void test1(A a){ 
    第3行 a = new A();//新加的一行 
    第4行 a.age = 20; 
    第5行 System.out.println("test1方法中的age="+a.age); 
    第6行 } 
    第7行 public static void main(String[] args) { 
    第8行 TempTest t = new TempTest(); 
    第9行 A a = new A(); 
    第10行 a.age = 10; 
    第11行 t.test1(a); 
    第12行 System.out.println(”main方法中的age=”+a.age); 
    第13行 } 
    第14行} 
    第15行class A{ 
    第16行 public int age = 0; 
    第17行} 
    运行结果为: 
    test1方法中的age=20 
    main方法中的age=10 为什么这次的运行结果和前面的例子不一样呢,还是使用内存示意图来理解一下 6:再次理解按引用传递 
    (1):运行开始,运行第9行,创建了一个A的实例,内存分配示意如下: 
    (2):运行第10行,是修改A实例里面的age的值,运行后内存分配示意如下: 
    (3):运行第11行,是把main方法中的变量a所引用的内存空间地址,按引用传递给test1方法中的a变量。请注意:这两个a变量是完全不同的,不要被名称相同所蒙蔽。 内存分配示意如下: 
    由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图如下: 
    也就是说:是两个变量都指向同一个空间。 (4):运行第3行,为test1方法中的变量a重新生成了新的A实例的,完成后形成的新的内存示意图如下: 
    (5):运行第4行,为test1方法中的变量a指向的新的A实例的age进行赋值,完成后形成的新的内存示意图如下: 
    注意:这个时候test1方法中的变量a的age被改变,而main方法中的是没有改变的。 (6):运行第5行,根据此时的内存示意图,输出test1方法中的age=20 
    (7):运行第12行,根据此时的内存示意图,输出main方法中的age=10 7:说明 
    (1):“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。 
    (2):在Java里面只有基本类型和按照下面这种定义方式的String是按值传递,其它的都是按引用传递。就是直接使用双引号定义字符串方式:String str = “Java私塾”; 
      

  2.   

    2楼,
    送(房子 fz){}
    Java 中你有任何方式搬房子吗?没有,你永远只能够用纸条。送(房子 fz){}它的形参就是处理纸条,你传递的纸条被我抄了一次,不是你写的。
      

  3.   

    3楼
    ,那篇我看过,也称其为说“按引用传递”的典型人物
    Thinking in Java作者是我知道的可能最有名的典型人物
      

  4.   

    我见过的强调java只有值传递的书: 
    Core Java  作者 : Cay S.Horstmann,Gary Cornell
    THE Java™ Programming Language  By Ken Arnold, James Gosling, David Holmes2.6.5. Parameter Values
    All parameters to methods are passed "by value." Java in a Nutshell, By David Flanagan2.9.4. Terminology: Pass by Value
    I've said that Java handles objects "by reference." Don't confuse this with the phrase "pass by reference." "Pass by reference" is a term used to describe the method-calling conventions of some programming languages. In a pass-by-reference language, valueseven primitive valuesare not passed directly to methods. Instead, methods are always passed references to values. Thus, if the method modifies its parameters, those modifications are visible when the method returns, even for primitive types.Java does not do this; it is a "pass by value" language. However, when a reference type is involved, the value that is passed is a reference. But this is still not the same as pass-by-reference. The Java Tutorials
    Passing Reference Data Type Arguments
    Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level. 
      

  5.   

    我的认为:
     1) 基本类型传的是值,java中任何传递对象的场合,都是传递对象的引用。(说java只按值传递的人,可能意思是引用也是个具体的值吧)。
     2)经典的就是, java编程思想(第4版 27页)
     3)C语言,我不清楚。
     4)我感觉没错,知道原理就可以,(好多书上都说java只按值传递,比如《java2入门经典》等)
      

  6.   

    上面列出的基本书里都有对pass by reference这个术语的介绍。理解了这个术语一切都清楚了。其实没有必要把时间花在这些争论上,只要理解具体的原理即可。
    你不能强迫别人介绍你的想法。
    c语言没有这个问题,因为c没有引用这个概念。
    c++有传引用这个术语,但是C++里的引用和java的引用根本不是一个概念。
      

  7.   

    8楼:
    pass by reference这个术语的语义有精确的定义:方法/函数操作实际参数本身。
    与有没有"引用" 这个概念无关。c语言中传递指针,也是按值传递,
    这才是我问“3、C语言也讨论“按引用传递”这个问题吗?”的原因。c语言没有这个问题,因为c没有引用这个概念。 【后面的原因不对】
    c++有传引用这个术语,但是C++里的引用和java的引用根本不是一个概念。【对】
      

  8.   

    10楼:
    不是吧?!
    我很少看国内Java教材。:(
      

  9.   

    4、为什么“按引用传递”是错误的?[不要讨论它错误之处,而是问一问他们的思路为什么错误】?
    其实关键问题就是这个术语的定义: In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value.
    java中明显处理的是copy,而不是原来的引用本身,从这个角度说,“pass by reference”这个术语是不合适的。但我想问题还是出在java设计时的术语选择上,比如Object obj;把这个obj称为“引用”,同时强调传参数时不是"pass by reference",本身就怪怪的。
      

  10.   

    一直感觉把java里的引用按指针来理解就没有这些问题了。
      

  11.   

    13楼 :
    ok,
    1、说“按引用传递”的人也是经过思考的,是不是他们使用了不同的术语,或者他们的术语不同于我们的术语? 
    你的帖子解决了这个问题。
    【Object obj;把这个obj称为“引用”】
    如果说“按引用传递”的人都是这样考虑问题的,那么错误明显。
    int i;i是值吗?不是。
    Object obj;obj是引用吗?不是。
      

  12.   

    14楼:
    java里的引用本身(可以说)就是一种指针,不过称为安全指针罢了。不可运算的指针。
      

  13.   

    “pass by reference”这个术语是不合适的。呵呵,是的。
    Java中接口的术语也讨厌的很,因为我们在非Java的环境中广泛使用的接口概念遇到它的干扰。
    虽然Java中接口的确是个很好的术语。
      

  14.   

    如果你认为不是,我只能说这叫Reference Type(引用类型)Object类的value(变量)了。
    刚学的时候曾经纠缠于这样的概念,也讨论过,其实很多人就是因为这个引用而“自然”地“传引用”了。
    不谈这个了。
      

  15.   


    我说了,《java编程思想》(第27页),
    我刚上面说的《java2入门经典》也说的是基本类型传的是值得副本,对象传的引用的副本。在那一页,我忘了,反正着本书讲的挺好的,用了3页讲这个知识点,还带图着呢,楼主这几天我也在琢磨这个的问题,昨天也发帖了, 还专门去书店查了下书。
      

  16.   


    哈,“Reference Type(引用类型)Object类的variable(变量)了”(你敲快了)
    没有这样夸张,obj一个变量麻,和i一样;不过是Reference Type。引用变量。
    int 类型的变量i也绕口。
      

  17.   

    21楼:
    谢谢。
    《java编程思想》(第27页),在它的第一版我就看见这个错误,还没有改过来,真硬气。
     《java2入门经典》,记住了。我看到的所有Java书,除TIJ,没有这样的说法。
    我看的都是国外的教材类或SUN相关的书,是不是教育机构的书只有按值传递,而普及类的书会出现“按引用传递”?
    这到有趣,,,
      

  18.   

    房子、纸条寓意很好。
    用它能够非常清楚地说明了Java中的按值传递。
      

  19.   


    对比几种译本 VS 原版讲解
    基础概念 Vs 奇技淫巧(茴香豆的第五种写法)
      

  20.   

    为什么JAVA只有按值传递?我觉得JAVA设计之初的承诺就是不让开发人员自己管理指针,另外JAVA里可以用包装类(wrapper)实现指针的效果,这相当于鼓励开发人员多封装,又侧面强调了面向对象思想
      

  21.   


    2 楼会改正其说法的.可以他敲快了,"1 我把房子搬着,然后把房子给你,这就是传值 "?
    foo(int i){}
    obj.foo(jjjj)我送你一个盒子jjjj如果我把jjjj这个盒子搬着,然后把盒子给你,典型的传引用!
      

  22.   

    我想这也是错怪了Thinking in Java了,我看的是第四版,里面有说明:
    Although you treat everything as an object, the identifier you manipulate is actually a “reference”
    to an object.
    对这句话有注释:
    1 This can be a flashpoint. There are those who say, “Clearly, it’s a pointer,” but this presumes an underlying
    implementation. Also, Java references are much more akin to C++ references than to pointers in their syntax. In
    the 1st edition of this book, I chose to invent a new term, “handle,” because C++ references and Java references
    have some important differences. I was coming out of C++ and did not want to confuse the C++ programmers
    whom I assumed would be the largest audience for Java. In the 2nd edition, I decided that “reference” was the
    more commonly used term, and that anyone changing from C++ would have a lot more to cope with than the
    terminology of references, so they might as well jump in with both feet. However, there are people who disagree
    even with the term “reference.” I read in one book where it was “completely wrong to say that Java supports pass
    by reference,” because Java object identifiers (according to that author) are actually “object references.” And (he
    goes on) everything is actually pass by value. So you’re not passing by reference, you’re “passing an object
    reference by value.” One could argue for the precision of such convoluted explanations, but I think my approach
    simplifies the understanding of the concept without hurting anything (well, the language lawyers may claim that
    I’m lying to you, but I’ll say that I’m providing an appropriate abstraction
    ).The Java Programming Language虽然强调pass by value,但是也支持不精确的表达,要不你每说一句话都强调,岂不是太累了.
    1.7.1. Creating Objects
    Most of the time, you can be imprecise in the distinction between actual objects and references to objects. You can say, "Pass the object to the method" when you really mean "Pass an object reference to the method." We are careful about this distinction only when it makes a difference. Most of the time, you can use "object" and "object reference" interchangeably.
    其实翻译成中文,Pass an object reference to the method.和pass by reference还有多大区别呢? 最后,没有必要强迫别人接受你的思想和概念.用java设计好程序比什么都强.
      

  23.   

    1.java没有"正规教材".
    2.大多数java书籍对于参数传递的具体特征都描述的清楚而且一致.
    3.他们有争议的,是这种传递方式的抽象命名而已.嘛~`嘛~`所以,无视这个问题就行了喵~~~``
      

  24.   

    34楼:
    你引用的第四版中说明和对这句话的注释,在第2版中就有,他真的是没有改.我们都会混用一些术语,没有人喜欢罗罗嗦嗦.
    如The Java Programming Language,混用了objects and references(to objects),
    Thinking in Java混用了什么?identifier (you manipulate) is (actually a) “reference” (to an object.) 关于Thinking in Java,假设世界上没有C++,只有C和fortran语言,我不知道他说的那些东西那里准确.Pass an object reference to the method.和pass by reference还有多大区别呢?
    如果你把所有的接口都认为是Java的接口,你就知道"接口和实现分离"是多么难以解释/理解.pass by reference是计算机语言中的一般术语,不是Java的.[最后,没有必要强迫别人接受你的思想和概念.用java设计好程序比什么都强.]
    常常听人说基础很重要,假设pass by reference这是一个基础问题,不存在强迫别人接受谁的思想和概念,它不包含新的概念,不过是在"when it makes a difference." We are careful about this distinction .
      

  25.   

    同楼上
    pass by reference里的reference和java里的reference不是一个意思
    core java里是正解
      

  26.   

    你说得很对.其实我开始就说了,Java只有按值传递,但是看见一些人反复讨论这个问题,不禁要问一下为什么?
    假设你是一个Java教师,和Thinking in Java的作者一样,你总要讲解Java只有按值传递,你不能够"无视这个问题"时,你总要说出自己的理由,怎么办?所以我想知道为什么?我一点都不想讨论pass by reference和pass by value本身.这一点在清楚不过了,
    我就是困惑:说“按引用传递”的人为什么这样想,如何避免你教的学生也出现类似的错误.1/java没有"正规教材". 我的意思是不讨论国内的一些垃圾教材,所以用了"正规"来形容.或者咱们说"能够上台面的教材"3.他们有争议的,是这种传递方式的抽象命名而已. //这是一句话就能够解决的问题,“按引用传递”是各种各样不错语言的传值方式之一,意思是方法操作实参本身.Java的引用和C语言的指针,它们都是copy后传递的.
      

  27.   

    本楼不讨论pass by reference和pass by value本身.
    讨论为什么有人会说“按引用传递”,他们的错误是那里来的,

      

  28.   

    可能誤解,就由這種高深見解而來的
    引用也是一個值,只是對引用的操作即是對引用所對應的實際對象進行操作而己
    從來java中就不能直接對對象進行操,只能以引用進行
    你何時傳遞過對象了?
      

  29.   

      北京亚历山大留学生机票,北京到亚历山大留学生特价机票,北京到亚历山大留学生飞机票">北京亚历山大留学生机票,北京到亚历山大留学生特价机票
        北京亚基马留学生机票,北京到亚基马留学生特价机票,北京到亚基马留学生飞机票">北京亚基马留学生机票,北京到亚基马留学生特价机票,北    北京里诺留学生机票,北京到里诺留学生特价机票,北京到里诺留学生飞机票">北京里诺留学生机票,北京到里诺留学生特价机票,北京到
        北京飞菲尼克斯(凤凰城)留学生机票,北京至菲尼克斯(凤凰城)留学生特价机票,北京到菲尼克斯(凤凰城)留学生机票">北京飞菲尼克斯(凤凰城)留学生机票,北京至菲尼克斯(凤    北京飞北本德留学生机票,北京至北本德留学生特价机票,北京到北本德留学生机票">北京飞北本德留学生机票,北京至北本德留学生特价机票,
        北京飞卡迈尔/蒙特雷留学生机票,至卡迈尔/蒙特雷留学生特价机票,到卡迈尔/蒙特雷留学生机票">北京飞卡迈尔/蒙特雷留学生机票,至卡迈尔/蒙特雷留学生    北京奥古斯塔留学生机票,北京到奥古斯塔留学生特价机票,北京到奥古斯塔留学生飞机票">北京奥古斯塔留学生机票,北京到奥古斯塔留学生特价机票
        北京到波尔图机票&至波尔图国际机票&飞波尔图特价机票查询预定">北京到波尔图机票&至波尔图国际机票&飞波尔图特价机票
      

  30.   

    我读过的一本java基础书上也说:java里面只有值传递。
    具体是这样的:
    基础数据类型就不说了,没有争议。
    关于对象,如:String str  = new String("xyz");书中认为引用str首先指向一对指针,这对指针分别指向对象的函数列表和数据,
    这样,所说的值传递就可以理解了,传递的都是str的值,也就是那对指针。
    我也认为这样理解比较合理。
      

  31.   

    String str  = new String("xyz");
      

  32.   

    Java只有按值传递?谁说的???
      

  33.   

    好像只能传值吧,JAVA和C,C++最大的不同,也是最大的改进,就是没有指针,都是传值的
      

  34.   

    JAVA中当然有搬房子啊! 比如数字1, 作为参数传递时,绝对是新建一个房子,然后传过去的。这个参数是实参,而不是什么纸条。
      

  35.   


    1、参数传递为什么重要?因为模块化。所以,obj.doSth(1)不在考虑访问之内。
    2、参数传递考虑:int i =5;
    A a = new A();
    obj.doSth(i);//doSth把纸条加10
    obj.doOtherSth(a);//doOtherSth把a指向我自己买的房子,
    print(i);//5 VS 15?
    a.装修();// 我自己 Vs 你写的
    传递的doOtherSth(a)不是房子,传递的是纸条。虽然被称为ref,但是传递的是其copy,按值传递。BTW:
    "1 我把房子搬着,然后把房子给你,这就是传值 " 不对 
    foo(int i){} 
    obj.foo(jjjj)我送你一个盒子jjjj如果我把jjjj这个盒子搬着,然后把盒子给你,典型的传引用! 盒子让你看一眼里面的东西,我带走盒子,按值传递。