`
topzhujia
  • 浏览: 56022 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

Java is Pass-by-Value!

    博客分类:
  • JAVA
阅读更多
<!--blog template-->
 
<style type="text/css"> <!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } H2 { margin-bottom: 0.21cm } H2.ctl { font-family: "Lohit Hindi" } PRE.cjk { font-family: "DejaVu Sans", monospace } H3 { margin-bottom: 0.21cm } H3.ctl { font-family: "Lohit Hindi" } A:link { so-language: zxx } --> </style>

Introduction

Pass-by-value
The actual parameter (or argument expression) is fully evaluated and the resulting value is copied into a location being used to hold the formal parameter's value during method/function execution. That location is typically a chunk of memory on the runtime stack for the application (which is how Java handles it), but other languages could choose parameter storage differently.
Pass-by-reference
The formal parameter merely acts as an alias for the actual parameter. Anytime the method/function uses the formal parameter (for reading or writing), it is actually using the actual parameter.

Java is strictly pass-by-value, exactly as in C. Read the Java Language Specification (JLS). It's spelled out, and it's correct. In http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.1:

When the method or constructor is invoked (15.12), the values of the actual argument expressions initialize newly created parameter variables, each of the declared Type, before execution of the body of the method or constructor. TheIdentifier that appears in the DeclaratorId may be used as a simple name in the body of the method or constructor to refer to the formal parameter.

[In the above, values is my emphasis, not theirs]

In short: Java has pointers and is strictly pass-by-value. There's no funky rules. It's simple, clean, and clear. (Well, as clear as the evil C++-like syntax will allow ;)

Note: See the note at the end of this article for the semantics of remote method invocation (RMI). What is typically called "pass by reference" for remote objects is actually incredibly bad semantics.


The Litmus Test

There's a simple "litmus test" for whether a language supports pass-by-reference semantics:

Can you write a traditional swap(a,b) method/function in the language?

A traditional swap method or function takes two arguments and swaps them such that variables passed into the function are changed outside the function. Its basic structure looks like

Figure 1: (Non-Java) Basic swap function structure

swap(Type arg1, Type arg2) {
     Type temp = arg1;
     arg1 = arg2;
     arg2 = temp;
}

If you can write such a method/function in your language such that calling

Figure 2: (Non-Java) Calling the swap function

Type var1 = ...;
Type var2 = ...;
swap(var1,var2);

actually switches the values of the variables var1 and var2, the language supports pass-by-reference semantics.

For example, in Pascal, you can write

Figure 3: (Pascal) Swap function

procedure swap(var arg1, arg2: SomeType);
    var
    temp : SomeType;
    begin
    temp := arg1;
    arg1 := arg2;
    arg2 := temp;
    end;
                       
    ...
    { in some other procedure/function/program }
    var
    var1, var2 : SomeType;
    begin
    var1 := ...; { value "A" }
    var2 := ...; { value "B" } 
    swap(var1, var2);
    { now var1 has value "B" and var2 has value "A" }
    end;

or in C++ you could write

Figure 4: (C++) Swap function

void swap(SomeType& arg1, Sometype& arg2) {
    SomeType temp = arg1;
    arg1 = arg2;
    arg2 = temp;
}
                    
 ...
                
SomeType var1 = ...; // value "A"
SomeType var2 = ...; // value "B"
swap(var1, var2); // swaps their values!
// now var1 has value "B" and var2 has value "A"

(Please let me know if my Pascal or C++ has lapsed and I've messed up the syntax...)

But you cannot do this in Java!


Now the details...

The problem we're facing here is statements like

In Java, Objects are passed by reference, and primitives are passed by value.

This is half incorrect. Everyone can easily agree that primitives are passed by value; there's no such thing in Java as a pointer/reference to a primitive.

However, Objects are not passed by reference. A correct statement would be Object references are passed by value.

This may seem like splitting hairs, bit it is far from it. There is a world of difference in meaning. The following examples should help make the distinction.

In Java, take the case of

Figure 5: (Java) Pass-by-value example

public void foo(Dog d) {
     d = new Dog("Fifi"); // creating the "Fifi" dog
}
Dog aDog = new Dog("Max"); // creating the "Max" dog
// at this point, aDog points to the "Max" dog
foo(aDog);
// aDog still points to the "Max" dog

the variable passed in (aDog) is not modified! After calling foo, aDog still points to the "Max" Dog!

Many people mistakenly think/state that something like

Figure 6: (Java) Still pass-by-value...

public void foo(Dog d) { 
    d.setName("Fifi");
}

shows that Java does in fact pass objects by reference.

The mistake they make is in the definition of

Figure 7: (Java) Defining a Dog pointer

Dog d;

itself. When you write that definition, you are defining a pointer to a Dog object, not a Dog object itself.

On Pointers versus References...

The problem here is that the folks at Sun made a naming mistake.

In programming language design, a "pointer" is a variable that indirectly tracks the location of some piece of data. The value of a pointer is often the memory address of the data you're interested in. Some languages allow you to manipulate that address; others do not.

A "reference" is an alias to another variable. Any manipulation done to the reference variable directly changes the original variable.

Check out the second sentence of http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1.

"The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object"

They emphasize "pointers" in their description... Interesting...

When they originally were creating Java, they had "pointer" in mind (you can see some remnants of this in things like
NullPointerException).

Sun wanted to push Java as a secure language, and one of Java's advantages was that it does not allow pointer arithmetic as C++ does.

They went so far as to try a different name for the concept, formally calling them "references". A big mistake and it's caused even more confusion in the process.

There's a good explanation of reference variables at http://www.cprogramming.com/tutorial/references.html. (C++ specific, but it says the right thing about the concept of a reference variable.)

The word "reference" in programming language design originally comes from how you pass data to subroutines/functions/procedures/methods. A reference parameter is an alias to a variable passed as a parameter.

In the end, Sun made a naming mistake that's caused confusion. Java has pointers, and if you accept that, it makes the way Java behaves make much more sense.

Calling Methods

Calling

Figure 8: (Java) Passing a pointer by value

foo(d);

passes the value of d to foo; it does not pass the object that d points to!

The value of the pointer being passed is similar to a memory address. Under the covers it may be a tad different, but you can think of it in exactly the same way. The value uniquely identifies some object on the heap.

However, it makes no difference how pointers are implemented under the covers. You program with them exactly the same way in Java as you would in C or C++. The syntax is just slightly different (another poor choice in Java's design; they should have used the same -> syntax for de-referencing as C++).

In Java,

Figure 9: (Java) A pointer
Dog d;

is exactly like C++'s

Figure 10: (C++) A pointer

Dog *d;

And using

Figure 11: (Java) Following a pointer and calling a method

d.setName("Fifi");

is exactly like C++'s

Figure 12: (C++) Following a pointer and calling a method

d->setName("Fifi");

To sum up: Java has pointers, and the value of the pointer is passed in. There's no way to actually pass an object itself as a parameter. You can only pass a pointer to an object.

Keep in mind, when you call

Figure 13: (Java) Even more still passing a pointer by value

foo(d);

you're not passing an object; you're passing a pointer to the object.

For a slightly different (but still correct) take on this issue, please see http://www-106.ibm.com/developerworks/library/j-praxis/pr1.html. It's from Peter Haggar's excellent book, Practical Java.)


A Note on Remote Method Invocation (RMI)

When passing parameters to remote methods, things get a bit more complex. First, we're (usually) dealing with passing data between two independent virtual machines, whi

分享到:
评论

相关推荐

    世界五百强java面试题下载

    - Stack Overflow上的相关讨论:https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value 通过以上分析和扩展阅读,希望能帮助大家更好地理解和掌握Java中对象传递的关键概念。

    servlet2.4doc

    A filter configuration object used by a servlet container to pass information to a filter during initialization. flushBuffer() - Method in interface javax.servlet.ServletResponse Forces any content ...

    Java邮件开发Fundamentals of the JavaMail API

    The Simple Mail Transfer Protocol (SMTP) is defined by RFC 821 . It defines the mechanism for delivery of e-mail. In the context of the JavaMail API, your JavaMail-based program will communicate ...

    Java中带参无返回值方法的使用共4页.pdf.zip

    Java采用传值调用(pass-by-value)机制。这意味着当参数传递到方法时,实际传递的是变量的副本,而不是变量本身。因此,方法内部对参数的修改不会影响到方法外部的变量值。 3. 方法调用: 调用无返回值方法时,只...

    已解决:No &#39;Access-Control-Allow-Origin&#39;跨域问题

    解决这个问题的方法有很多种,但在Java环境中,特别是使用Tomcat服务器时,一个简洁有效的解决方案是通过配置CORS Filter。CORS(Cross-Origin Resource Sharing)是一种机制,它使用额外的HTTP头部来告诉浏览器允许...

    JSP Simple Examples

    Forms are used to pass user- data to a specified URL which is specified in the action attribute of the form tag. Interface in jsp In interface none of its methods are implemented. All the methods ...

    Google C++ Style Guide(Google C++编程规范)高清PDF

    The goal of this guide is to manage this complexity by describing in detail the dos and don'ts of writing C++ code. These rules exist to keep the code base manageable while still allowing coders to ...

    Fortran面试题.pdf

    - **按值传递(Pass-by-value):** 传递的是变量的副本,不会改变原始变量。 - **按引用传递(Pass-by-reference):** 传递的是变量的引用,修改将反映到原始变量上。 2. **接口(Interface)的作用及使用:** ...

    Effective C++ 中文版

    条款20:宁以pass-by-reference-to-const替换Pass-by-value 条款21:必须返回对象时,别妄想返回其reference 条款22: 将成员变量声明为private 条款23: 宁以non-member、non-friend替换member函数 条款24:若...

    C Programming

    In this section, the document begins by explaining the fundamentals of computers, which is essential for understanding programming and the context in which C programming operates. It covers: - **...

    tomcat-5.5.23

    Directory used by the JVM for temporary files (java.io.tmpdir) &lt;br&gt;If you do not pass the "-Dcatalina.base=$CATALINA_BASE" argument to the startup command, $CATALINA_BASE will default to the ...

    CE中文版-启点CE过NP中文.exe

    ExecuteCodeEx(Let's you execute code in the target and pass parameters) Added 2 new parameters to getNameFromAddress (ModuleNames and Symbols) Added addModule and deleteModule to the symbollist class ...

    GifDecoder

    * frames as specified by their disposition codes). */ protected void setPixels() { // expose destination image's pixels as int array int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer...

    ORACLE转DB2对照全解

    TYPE t1 IS TABLE OF NUMBER INDEX BY PLS_INTEGER; t1_tab t1; ``` **DB2:** ```sql DECLARE t1_tab TABLE(NUMBER) WITH DEFAULT STORAGE; ``` **注意:** Oracle支持基于PL/SQL的表类型,而DB2则提供了一种更...

    Python岗位常规面试题.pdf

    print("You cannot divide by zero!") except ValueError: print("Invalid input. Please enter a number.") finally: print("End of program") ``` #### 9. Python中的什么机制实现了元类(Metaclass)?请说明...

    测试培训教材

    WR-AUTOMATED A test that is executed by WinRunner, Mercury's functional testing tool for Microsoft Windows applications. LR-SCENARIO A scenario that is executed by LoadRunner, Mercury's load ...

    Python文档

    目前市场上的应用软件中有超过一半是面向网络的应用,如数据库服务器、游戏、Java Servlets 和 Applets、CGI 脚本等。数据通信不再是两台机器(本地网络或互联网)之间的奇技淫巧,而是日常生活中不可或缺的一部分。...

Global site tag (gtag.js) - Google Analytics