This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
I’ve read a lot of articles about how “pass-by-reference” doesn’t exist in Java since a copy of the value of the reference is passed, hence “pass-by-copy-of-reference-value”.
The articles also say a reference value is a pointer.
(So pointers do exist in Java.)
Some other articles say: Java has no pointers.
So what is the correct solution?
How does a pointer differ from a reference (or reference value), and do they exist in Java?
They aren't like C pointers. There's no pointer arithmetic allowed.
Java has only one mechanism for passing parameters: pass by value in all cases. For primitives, the value is passed. For objects, the reference to the object on the heap is passed.
A pointer is a reference type; it refers to something. What you're basically asking is: "Does Java have Dobermans? Because some articles say it has dogs."
As noted in Wikipedia entry for Pointer:
A pointer is a simple, more concrete implementation of the more abstract reference data type. Several languages support some type of pointer, although some have more restrictions on their use than others
It goes on to say this about Java specifically:
Unlike C, C++, or Pascal, there is no explicit representation of pointers in Java. Instead, more complex data structures like objects and arrays are implemented using references. The language does not provide any explicit pointer manipulation operators. It is still possible for code to attempt to dereference a null reference (null pointer), however, which results in a run-time exception being thrown. The space occupied by unreferenced memory objects is recovered automatically by garbage collection at run-time.
Looking up Reference you find:
In computer science, a reference is a value that enables a program to indirectly access a particular datum, such as a variable or a record, in the computer's memory or in some other storage device. The reference is said to refer to the datum, and accessing the datum is called dereferencing the reference.
A reference is distinct from the data itself. Typically, a reference is the physical address of where the data is stored in memory or in the storage device. For this reason, a reference is often called a pointer or address, and is said to point to the data. However a reference may also be the offset (difference) between the datum's address and some fixed "base" address, or an index into an array.
Java chose to use the broader term "reference" instead of "pointer" because of the differences between Java and C. (Thus creating a sisyphus-like situation where we have to keep explaining that Java is pass-by-value).
You don't have a C pointer, you have a Java Reference. This has nothing to do with a C++ reference, or pass-by-reference.
Because Java is pass-by-value it is similar to using a C pointer in that when you pass it to a method, the value (e.g. memory address) is copied.
It is right to say both:)
Java has no pointers since java has simplified pointers as references.
Object o=new Object();
We got an object o here; o is actually a pointer.
Basically, pointers and references are the same thing; they point to (refer to) something else in memory. However, you cannot do integer arithmetic on references. You may find some pages on this slide useful:
http://www.cis.upenn.edu/~matuszek/cit594-2005/Lectures/15-pointers-and-references.ppt
You have to get your head around the different, but related concepts of types, variables and objects. If we ignore for now the fundamental types like int and only consider class types, then in Java there are variables, which are "named things", and objects. Both variables and objects have a type. However, a variable of type T is not an object; rather, it is a mechanism for locating an object of type T, and for informing the runtime that this object is in use. A variable may at any point not locate any object, in which case it is null, or it may, and in that case the very existence of the variable keeps the object alive.
Let's repeat: Variables have names. Objects don't have names. Variables are not objects.
When you pass a variable as an argument into a function call, the corresponding function parameter becomes duplicate of the argument, so that there are now two variables which both locate the same object. When you assign one variable to another, you make the left-hand variable locate the same object (possibly null) as the right-hand variable, relinquishing the possibly previously held location. But no objects are being affected by this; the objects exist in some unrelated, unprobable plane of existence.
Also, variables have a deterministic lifetime, which is determined by their scope (essentially block-local or static-global). The lifetime of variables is non-deterministically related to the lifetime of objects, but the lifetime of objects cannot be controlled directly.
That's the type system and object model of Java (for class types) in a nutshell. It's up to you what you want to label this; it makes sense to say that "variables are references", since that's what they do, but you might as well just stop trying to compare yourself to other languages and just say "variables", which is clear enough within the context of Java. Variables are variables, objects are objects, neither one is ever the other, and you need the former to talk about the latter.
In Java, a reference is a pointer, usually one that isn't null. That's why it's called NullPointerException, not NullReferenceException. "The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object. "
Java pointers/references are akin to Pascal pointers, not to C or C++ pointers, in that they are very strongly typed and do not support address arithmetic.
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 2 years ago.
Arrays are not a primitive type in Java, but they are not objects either, so are they passed by value or by reference? Does it depend on what the array contains, for example references or a primitive type?
Everything in Java is passed by value. In case of an array (which is nothing but an Object), the array reference is passed by value (just like an object reference is passed by value).
When you pass an array to other method, actually the reference to that array is copied.
Any changes in the content of array through that reference will affect the original array.
But changing the reference to point to a new array will not change the existing reference in original method.
See this post: Is Java "pass-by-reference" or "pass-by-value"?
See this working example:
public static void changeContent(int[] arr) {
// If we change the content of arr.
arr[0] = 10; // Will change the content of array in main()
}
public static void changeRef(int[] arr) {
// If we change the reference
arr = new int[2]; // Will not change the array in main()
arr[0] = 15;
}
public static void main(String[] args) {
int [] arr = new int[2];
arr[0] = 4;
arr[1] = 5;
changeContent(arr);
System.out.println(arr[0]); // Will print 10..
changeRef(arr);
System.out.println(arr[0]); // Will still print 10..
// Change the reference doesn't reflect change here..
}
Your question is based on a false premise.
Arrays are not a primitive type in Java, but they are not objects either ... "
In fact, all arrays in Java are objects1. Every Java array type has java.lang.Object as its supertype, and inherits the implementation of all methods in the Object API.
... so are they passed by value or by reference? Does it depend on what the array contains, for example references or a primitive type?
Short answers: 1) pass by value, and 2) it makes no difference.
Longer answer:
Like all Java objects, arrays are passed by value ... but the value is the reference to the array. So, when you assign something to a cell of the array in the called method, you will be assigning to the same array object that the caller sees.
This is NOT pass-by-reference. Real pass-by-reference involves passing the address of a variable. With real pass-by-reference, the called method can assign to its local variable, and this causes the variable in the caller to be updated.
But not in Java. In Java, the called method can update the contents of the array, and it can update its copy of the array reference, but it can't update the variable in the caller that holds the caller's array reference. Hence ... what Java is providing is NOT pass-by-reference.
Here are some links that explain the difference between pass-by-reference and pass-by-value. If you don't understand my explanations above, or if you feel inclined to disagree with the terminology, you should read them.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm
http://www.cs.fsu.edu/~myers/c++/notes/references.html
Related SO question:
Is Java "pass-by-reference" or "pass-by-value"?
Historical background:
The phrase "pass-by-reference" was originally "call-by-reference", and it was used to distinguish the argument passing semantics of FORTRAN (call-by-reference) from those of ALGOL-60 (call-by-value and call-by-name).
In call-by-value, the argument expression is evaluated to a value, and that value is copied to the called method.
In call-by-reference, the argument expression is partially evaluated to an "lvalue" (i.e. the address of a variable or array element) that is passed to the calling method. The calling method can then directly read and update the variable / element.
In call-by-name, the actual argument expression is passed to the calling method (!!) which can evaluate it multiple times (!!!). This was complicated to implement, and could be used (abused) to write code that was very difficult to understand. Call-by-name was only ever used in Algol-60 (thankfully!).
UPDATE
Actually, Algol-60's call-by-name is similar to passing lambda expressions as parameters. The wrinkle is that these not-exactly-lambda-expressions (they were referred to as "thunks" at the implementation level) can indirectly modify the state of variables that are in scope in the calling procedure / function. That is part of what made them so hard to understand. (See the Wikipedia page on Jensen's Device for example.)
1. Nothing in the linked Q&A (Arrays in Java and how they are stored in memory) either states or implies that arrays are not objects.
Arrays are in fact objects, so a reference is passed (the reference itself is passed by value, confused yet?). Quick example:
// assuming you allocated the list
public void addItem(Integer[] list, int item) {
list[1] = item;
}
You will see the changes to the list from the calling code. However you can't change the reference itself, since it's passed by value:
// assuming you allocated the list
public void changeArray(Integer[] list) {
list = null;
}
If you pass a non-null list, it won't be null by the time the method returns.
No that is wrong. Arrays are special objects in Java. So it is like passing other objects where you pass the value of the reference, but not the reference itself. Meaning, changing the reference of an array in the called routine will not be reflected in the calling routine.
Everything in Java is passed by value .
In the case of the array the reference is copied into a new reference, but remember that everything in Java is passed by value .
Take a look at this interesting article for further information ...
The definitive discussion of arrays is at http://docs.oracle.com/javase/specs/jls/se5.0/html/arrays.html#27803 . This makes clear that Java arrays are objects. The class of these objects is defined in 10.8.
Section 8.4.1 of the language spec, http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#40420 , describe how arguments are passed to methods. Since Java syntax is derived from C and C++, the behavior is similar. Primitive types are passed by value, as with C. When an object is passed, an object reference (pointer) is passed by value, mirroring the C syntax of passing a pointer by value. See 4.3.1, http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.3 ,
In practical terms, this means that modifying the contents of an array within a method is reflected in the array object in the calling scope, but reassigning a new value to the reference within the method has no effect on the reference in the calling scope, which is exactly the behavior you would expect of a pointer to a struct in C or an object in C++.
At least part of the confusion in terminology stems from the history of high level languages prior to the common use of C. In prior, popular, high level languages, directly referencing memory by address was something to be avoided to the extent possible, and it was considered the job of the language to provide a layer of abstraction. This made it necessary for the language to explicitly support a mechanism for returning values from subroutines (not necessarily functions). This mechanism is what is formally meant when referring to 'pass by reference'.
When C was introduced, it came with a stripped down notion of procedure calling, where all arguments are input-only, and the only value returned to the caller is a function result. However, the purpose of passing references could be achieved through the explicit and broad use of pointers. Since it serves the same purpose, the practice of passing a pointer as a reference to a value is often colloquially referred to a passing by reference. If the semantics of a routine call for a parameter to be passed by reference, the syntax of C requires the programmer to explicitly pass a pointer. Passing a pointer by value is the design pattern for implementing pass by reference semantics in C.
Since it can often seem like the sole purpose of raw pointers in C is to create crashing bugs, subsequent developments, especially Java, have sought to return to safer means to pass parameters. However, the dominance of C made it incumbent on the developers to mimic the familiar style of C coding. The result is references that are passed similarly to pointers, but are implemented with more protections to make them safer. An alternative would have been the rich syntax of a language like Ada, but this would have presented the appearance of an unwelcome learning curve, and lessened the likely adoption of Java.
In short, the design of parameter passing for objects, including arrays, in Java,is esentially to serve the semantic intent of pass by reference, but is imlemented with the syntax of passing a reference by value.
Kind of a trick realty... Even references are passed by value in Java, hence a change to the reference itself being scoped at the called function level. The compiler and/or JVM will often turn a value type into a reference.
In Java, when we assign an object to a variable of the matching class type, the variable only contains a reference to the memory location where the object in stored.
Is the case same with Primitive data types as well?
I mean, in int i = 10;, does i store the address of the memory location where the value 10 is stored?
PS: In sharp contrast, C++ actually stores the objects and not the references, right? Unless we use pointers and reference variables, right?
In Java, everything is stored by value. The value of an Object type in contrast to a primitive is the reference. Note that the wrapper types (like Integer) do constant interning for low values.
Indeed, in Java, primitives are always handled by value and objects are always handled by reference. Note however that these are the semantics; i.e., what the meaning of Java code is supposed to be. A particular implementation of Java (i.e., a JVM) is free to manage memory however it likes internally, as long as it appears to obey the correct semantics for anything that can be observed (i.e., output of the program).
And your PS remark is also correct.
Before I post my question, I have read the following excellent articles on java-pass-by-value.
I am convinced I have understood it well.
Is Java "pass-by-reference" or "pass-by-value"?
http://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html
My question has to do with a side-by comparison of Java with other language that supports pass-by-reference(C++ may be).
In case of Java, you have a handle (reference) pointing to the object in location A. so object itself could be modified. But It is not possible to change the object location itself.
I.e An object stored in memory address 0X945 cannot be changed to 0X948.
In languages such as C++, you can choose to pass-by-value or pass-by-reference. (It is in the hands of the programmer correct?). Hence it is possible to change the location of object in memory space correct?
P.S: I have good background on Java but on C++. so my views above may be wrong.
It is claimed in the article 1, I cited above that there is no notion of pointers in Java. I dont know how far that is true? (why do NullPointerException exists then)
EDIT:
consider this example:
void swap(Object A,Object B) {
Object temp=B;
Object B=A;
Oject A=temp;
}
when I call the method in Java such as swap(A,B), nothing happens
but in C++ (I presume), swap happens. which probably means I am changing the location of objects in memory correct?
In java even - references to objects are passed by value. i.e, everything is pass-by-value. Next,
you can choose to pass-by-value or pass-by-reference. (It is in the hands of the programmer correct?).
Correct. But you can't do it in Java.
An object stored in memory address 0X945 cannot be changed to 0X948.
You can't do this in both java and C++.
NullPointerException is thrown when you try to access a property / method of something which doesn't exist (is null). i.e, the reference points to null when an instance of the object is required.
Object o = null;
o.toString() --> NPE. o points to null.
so in C++, do pass-by-reference means you pass the object itself, so that it could be reassigned in swap method
In C++, pass by reference, swap(Object &A, Object &B) appears to be close to java's pass by value.
In Java Object A is a reference to an Object and is null by default. As Object is already a reference and so when this reference is copied, it is passed by value.
In C++, Object A is an instance of an Object and is always a unique object. As Object is an instance, you are passing by reference using Object& because the Object is not passed, but a reference to it.
Java is always pass by value, it's just when you are passing objects, the value passed is the location in memory so it can act like pass by reference.
when I call the method in Java such as swap(A,B), nothing happens but
in C++ (I presume), swap happens.
No it doesn't. "Nothing" also happens in C++.
A correct translation of the code to C++ would be:
void swap(Object *A,Object *B) {
Object *temp=B;
B=A;
A=temp;
}
(Yes, the syntax for types is different between the languages. Namely, the pointer-to-Foo type is written as Foo * in C++ and Foo in Java; that's just a syntactical difference between the languages.)
In some Java literature, The statement
The reference type of the Java virtual
machine is cleverly named
reference
is widely popular. However, authors tend not to explain more why such statement is valid. Another thing that would make me understand this more is
What does the reference type of the JVM means ? Does the JVM represent itself in the heap ?
Would appreciate a lot an explanation on this statement.
Thank you,
Ashmawy
The word you're looking for here is irony:
the use of words to convey a meaning that is the opposite of its literal meaning
The use of "clever" in that sentence is clearly ironic. "The reference type of the Java virtual machine is given the clearly really stupidly obvious name 'reference'" is another way to read that sentence.
I think the cleverly part relates to the fact that a reference type is typically called a pointer, which necessitates the reader to learn two terms. The JVM terminology simply uses the term reference for this.
There's also a historical context.
When Java was introduced, its biggest competitor was C++. C++'s main problem was that it was deemed to be too difficult. Java initially positioned itself as the easy alternative to C++. It had a syntax very close to C++, but all the difficult stuff (operator overloading, templates, multiple pass-by mechanisms) etc were removed from the language.
And now comes the catch...
Java was initially marketed as not having pointers. The rationale for saying this was that pointers were deemed the most difficult thing of C++, so if Java would not have them, it had to be a simpler language.
The clever part thus comes from simply inventing another term for 'pointer'. Call them reference and you can state Java does not have pointers (but references).
This has lead to many debates and caused a good amount of confusion, especially since C++ already had the term 'reference' and uses it for something else (though conceptually a little related). The debate usually centers around two camps where one of them claims Java indeed does not have pointers, since you can't do pointer arithmetic with them and they don't directly represent memory addresses, while the other camp states that you don't have to be able to do arithmetic with a pointer to call it a pointer.
Put differently, whether it was clever to use the term reference is still open for debate.
This becomes clearer when the whole paragraph is taken into context:
The reference type of the Java virtual machine is cleverly named reference. Values of type reference come in three flavors: the class type, the interface type, and the array type. All three types have values that are references to dynamically created objects. The class type's values are references to class instances. The array type's values are references to arrays, which are full-fledged objects in the Java virtual machine. The interface type's values are references to class instances that implement an interface. One other reference value is the null value, which indicates the reference variable doesn't refer to any object.
(Taken from http://javadeveloper-jayaprakash-m.blogspot.com/)
I would assume from this that the "cleverly named" bit is referring to the fact that the references come in three different types and the JVM can distinguish between each one.
Or maybe it is only notion to express different approach taken by JVM designers for memory management.
If you'll remember in C/C++ one have freedom to allocate memory for variable either in local stack or in global heap. It is possible in C++ to allocate memory for object in method's local stack and then pass entire object as a parameter to other methods.
Java designers took away this freedom from developers. You just cannot create objects in local stack, only in global heap. So every variable of type Class/Interface/Array is indeed a reference to some memory address in the heap. And you cannot pass object by value only by reference.
If you don't have a choice - than you don't even need to think about what type of variable you have - value type or reference type.
What's your deep comprehension of pointer,reference and Handle in C,C++ and Java?
We usually think about the pointer,reference and Handle on the specify language level, it's easy to make confusion by the newbie like me.
Actually all those concept in java, just a encapsulation of pointer.
All pointer just a encapsulation of main memory addresses .
So all of those ,just a encapsulation wiles.
all above, it's my personal glimpse. And what's your comprehension ?
welcome to share with me.
Each language has differences to this respect. In C there are only pointers that are variables holding a memory address. In C you can use pointer arithmetic to move through memory, if you have an array, you can get a pointer to the first element and navigate the memory by incrementing the pointer.
Java references are similar to pointers in that they refer to a location in memory, but you cannot use pointer arithmetic on them. Only assignments are allowed. Note that the reference is not the object, but a way of accessing an object. This can be seen in argument passing semantics: objects are not passed by reference, references are passed by value:
public static void swap( Object o1, Object o2 )
{
Object tmp = o1;
o1 = o2;
o2 = tmp;
}
The previous piece of code is a complex no-op. References to two objects are passed by value, they are played with inside the method and nothing happens from the caller perspective: the real objects do not suffer any change, nor do the references the caller has into those objects. That is, if the call is swap( ref1, ref2 ), the system will make copies of the references into o1 and o2, the copies are changed within the method, but the caller variables ref1 and ref2 will remain unchanged after the method call.
In C++ you have two concepts: pointers are the same as C pointers and close to Java references, while C++ references are aliases into the objects they refer. C++ references can only be initialized with one object/data element in construction and from there on, using the original object and the reference is exactly the same. Besides the fact that references don't hold the resource and thus the destructor will not be called when the reference goes out of scope, nor will the reference notice if the referred object is destroyed, for all other uses the two names are the same element.
template <typename T>
void swap( T & a, T & b )
{
T tmp( a );
a = b;
b = tmp;
}
The code above in C++ differs from the Java version in that it does change the caller objects. If a caller uses swap( var1, var2 ), then the references are bound to those variables, and it is var1 and var2 the ones that suffer the change. After the call, the value of var1 and var2 is actually swapped.
Handles are in a different level, they are not language construct but tokens provided by a library so that you can later on refer to some resource that the library manages internally. The most general case are integer handles that are ids (or offsets) into a resource table, but I have seen strings used as handles. It is the library internally who decides what is exactly a handler (a pointer, an integer, a string or a more complex data structure). Handles are meant to be opaque in that the only sensible use is to store them and later give it back to the same library as part of other function signatures.
In C++ a pointer is a variable that points to a location in memory. You can access the object or data stored there by dereferencing the pointer. A reference is simply a pointer that has two distinctions from a pointer. First, you cannot change what a reference points to once the reference is initialized. Second the dereferencing semantics are removed so you can access a reference as if it were an object allocated on the stack instead of on the heap with new.
In Java, there are no pointers, only references. Every object you use is a reference to an object allocated on the heap. The downside is you can't do pointer math tricks. That's also the upside.
EDIT:
As pointed out in the comments, a Java reference differs from a C++ reference in that it can be reassigned once initialized. They are still called 'reference types' by the language specification, but behaviorally they act like pointers in terms of being able to be reassigned and passed to functions, but the semantics of dereferencing them look like non-pointer access looks in C++.