Why does this work, displaying array in sorted order?:
Integer[] array={7,5,9,3,6,0,2,4};
MergeSort.mergeSort(array,0,7);
System.out.println(Arrays.toString(array));
Specifically, why does passing array to a public static void method mergeSort end up modifying the array itself? I thought that Java protected from this. For example this code:
public static void main(String[] args){
int c=2;
change(c);
System.out.print(c);
}
public static void change(int c){
c=4;
}
returns 2 instead of 4. I am confused why Java allows you to modify an array passed as a parameter, but not an int
Because Java is pass by value, and when you pass an Object (and array is an Object) you pass the value of the reference to the Object. In contrast, a primitive has no reference so you just pass the value.
Edit
Similarly, you could have used the built in Arrays.sort() method to sort your array. Java arrays are not primitive types. In Java, the primitive wrapper types are immutable (like String). Consider,
private static void change(String in) {
in = in + " World"; // <-- modifies in here, can't change caller's reference.
}
private static void change(StringBuilder in) {
in.append(" World"); // <-- uses reference from caller.
}
public static void main(String[] args) {
String str = "Hello";
StringBuilder sb = new StringBuilder(str);
change(str);
change(sb);
System.out.println("one: " + str);
System.out.println("two: " + sb);
}
When using an array, taken as a parameter or not, consider that arr[i] is a pointer to some location of the memory. Then, when receiving an array as a parameter, you have a new reference pointing to the same array object. That means that in your method, instructions such as :
myParameterArray = new int[5];
won't modify the input array, because you are just changing the value of a reference, not the value pointed by it. Nevertheless, instructions such as :
myParameterArray[i] = 5;
will directly modify your input array. That is how methods like Arrays.sort work.
Related
When I passing an object reference (arrays are objects) to a method, the value is passed, right?
In the following code the initial value is: 333. After method passing, the value is changed. Why? Is in this case the reference passed instead the value?
Are arrays "special cases"?
public static void main(String[] args) {
int[] myArray = { 333 };
valueOrRef(myArray); // Value or Reference?
System.out.println(myArray[0]); // 777 (changed)
}
public static void valueOrRef(int[] myArgument) {
myArgument[0] = 777;
}
Another approach: (the logic "pass by value"):
public static void main(String[] args) {
int[] myArray = { 333 };
valueOrRef(myArray[0]); // Value or Reference?
System.out.println(myArray[0]); // 333 (after method still unchanged)
}
public static void valueOrRef(int myArray2) {
myArray2 *= 2;
}
The value is always passed, but keep in mind that for arrays the value is in fact a reference to an array and not the array itself.
The first valueOrRef method changes the content of the array pointed at by myArgument which is why you see the effect on the array after calling the method.
New to Java here, please help. How arguments are passed in java? Why am I unable to change argument value in the calling method from within called method?
Code
public class PassTest {
public static void changeInt(int value)
{
value=55;
}
int val;
val=11;
changeInt(val);
System.out.println("Int value is:" + val);// calling modifier changeInt
}
Output
Int value is: 11
why it is not 55..?
Java passes by value, not by reference. In your method value contains a copy of the value from val. Modifying the copy does not change the original variable.
You could pass an int wrapped inside an object if you want your changes to be visible to the caller. You can for example use the class org.apache.commons.lang.mutable.MutableInt.
Java : Best way to pass int by reference
Java passes ByValue, meaning the value of the object you put as a parameter is passed, but not the object itself, therefore
val=11;
changeInt(val);
does the exact same thing as
int val=11;
int val2=val
changeInt(val2);
int is a primitive, primitives don't "wrap" a value, you could try to use an Integer class, or make your own class that stores an integer, and then change that classes integer value. Instances of an object are sometimes passed ByReference if setup right. here is an example
MyStringClass.java
public class MyStringClass{
private String string = null;
public MyStringClass(String s){
string = s;
}
public String getValue(){
return string;
}
public void setValue(String s){
string = s;
}
}
and then the workings
public static void addTo(String s){
s += " world";
}
public static void addTo(MyStringClass s){
s.setValue(s.getValue() + " world");
}
public static void main(String[] args){
String s = "hello";
MyStringClass s1 = new MyStringClass("hello");
addTo(s);
addTo(s1);
System.out.println(s);//hello
System.out.println(s1);//hello world
}
I would wonder why you need to change the value instead of just returning it? isn't it easier?
Java passes by Value, it makes a copy which is completely dis-associated with the original variable reference, which means it doesn't have access to change the original int. This is true for primitives as well as object references as well.
You can use AtomicInteger or something like it, to achieve what you are desiring to do.
Primitive variables are passed by value not reference as you are suggesting.
As others said, Java passes byValue by default which means that you are just getting a copy in the function. You can pass byReference, which will pass a pointer to the object and allow you to directly edit but this is not seen as best practice. I would suggest doing it like this:
public class PassTest {
public int changeInt(int value)
{
value = 55;
return value;
}
int val;
val=11;
val = changeInt(val);
System.out.println("Int value is:" + val);// calling modifier changeInt
Here is a Example to pass argument:
class Test {
int a,b;
public Test(int j, int k) {
a=j;
b=k;
}
void change(Test ko){
ko.a=ko.b+ko.a;
ko.a=ko.b-12;
}
}
class sdf {
public static void main(String[] args){
Test op=new Test(12,32);
System.out.println(op.a+" "+op.b);
op.change(op);
System.out.println(op.a+" "+op.b);
}
}
Take a look at this piece of code::
you can see , in this case the action inside change() have affected the object passed to the method
When an object reference is passed to the method ,the reference itself is passed to the method call-by-value . therefore , the parameter receives a copy of the reference used in this argument .As a result A change to the parameter (such as making it refers to the different object ) will not affect the reference used as the argument . however , since the parameter and the argument both refer to the same object , a change through the parameter will affect the object reffered by the argument.
Hi all I have an immutable array implementation which looks like this:
public static final class FixedArray<T> {
private final T[] array;
public final int Length;
#SafeVarargs
public FixedArray(T... args) {
array = args;
Length = args.length;
}
public T Get(int index) {
return array[index];
}
}
public static final class FixedIntArray {
private final int[] array;
public final int Length;
public FixedIntArray(int... args) {
array = args;
Length = args.length;
}
public int Get(int index) {
return array[index];
}
}
public static final class FixedLongArray {
private final long[] array;
public final int Length;
public FixedLongArray(long... args) {
array = args;
Length = args.length;
}
public long Get(int index) {
return array[index];
}
}
Initially I'd thought that it is guaranteed to be thread-safe. But after reading the discussion regarding immutable arrays and the Java Memory Model, I believe alone, I can't be sure.
I've not used a defensive copy, with the contract that the calling code "does the right thing" (and as usual, if it doesn't follow the contract, the behavior is undefined).
The calling method looks like this:
public static void main(String args[]) {
int[] ints = new int[10000];
FixedIntArray fixed_ints = new FixedIntArray(ints);
SendToThreadA(fixed_ints);
SendToThreadB(fixed_ints);
SendToThreadC(fixed_ints);
SendToThreadD(fixed_ints);
//caller (which is this method) does the right thing, ints goes out of scope without anyone trying to modify it.
}
I was wondering is the code above guaranteed to be thread-safe?
As we don't know what happens to the array (and its values) to which you store a reference, I think your classes would be much safer if the constuctors create a copy of the argument array and set the internal final reference to the copied array.
It's OK. You can require caller to "hand-off" the array to you. Caller can clone one if necessary.
Memory write is usually the most expensive thing in a program (sans external IO).
Not everybody is stupid. You only need to be defensive enough to protect your target user base.
Given that you can pass an array to a varargs method, you'd need to make a copy of the constructor input to ensure it can't be modified outside the class. Having done that, as long as you don't assign the final field until after all the values are assigned in the copy array, you should be fine because the assignment to the final field is guaranteed to happen before any read of that field from another thread.
So a constructor would look like:
array = Arrays.copyOf(args, args.length);
Orrrr you could just use a Guava ImmutableList and get a lot more power.
I'm not sure it's meaningful to examine it for thread-safety, because it's missing even a more basic level of safety. Consider this method:
public static void main(final String... args)
{
final int[] arr = new int[] { 3, 3, 3 };
final FixedIntArray threeThrees = new FixedIntArray(arr);
System.out.println(threeThrees.Get(0)); // prints "3"
System.out.println(threeThrees.Get(1)); // prints "3"
System.out.println(threeThrees.Get(2)); // prints "3"
arr[0] = arr[1] = arr[2] = 4;
System.out.println(threeThrees.Get(0)); // prints "4"
System.out.println(threeThrees.Get(1)); // prints "4"
System.out.println(threeThrees.Get(2)); // prints "4"
}
The problem is that, when a method that takes int... (or Object... or long... or anything else), it can receive either an array that's implicitly constructed by the compiler (as would happen if you typed new FixedIntArray(3,3,3)), or an array that's explicitly passed in by the calling code (as I did above). In the latter case, the calling code can continue to modify the array that it passed in!
I have the following function.
func(ArrayList `<String>`[] name) { ........ }
The function fills the ArrayList[]. (I don't want to return the ArrayList[])
However, in the caller function the ArrayList[] obtained has all ArrayLists as null.
For eg.
name = new ArrayList[num];
func(name);
System.out.println(name[0]);
I get NullPointerException at line 3. Is this because of line 1, i.e. I am not parametrizing? If yes, is there another way this can be done? Because java does not allow creating a generic array of parametrized ArrayList.
That is obviously not your real code, but you're creating an array of ArrayLists, which probably isn't what you want. You can probably just do:
ArrayList<String> name = new ArrayList(num);
func(name);
System.out.println(name.get(0));
Note that when you create the ArrayList, you're only specifying the initial capacity, not the size (number of initial items). It will have an initial size of 0. Your func can just call add to add items.
Even better (no typing errors):
ArrayList<String> name = new ArrayList<String>();
I recommend not bothering with the initial capacity argument (num) - just leave it blank and it will work perfectly. But do bother with the generic type of String in the constructor, or the compiler will complain.
If you want to know how to use the ArrayList (for example, why to use the get() function), you should look at the documentation.
For arrays in Java when you create it all of the elements are either 0, false, or null depending in their type.
So:
final List<String>[] foo;
foo = new ArrayList<String>[10];
foo[0].add("hello"); // crash
that crashes because foo = new ArrayList<String>[10]; allocates enough room to hold 10 ArrayList<String> but it sets all of the values to null. So you need one additional step:
for(int i = 0; i < foo.length; i++)
{
foo[i] = new ArrayList<String>();
}
I haven't compiled the code, but pretty sure it is all correct. You would do that between step 1 and 2 of your program.
I am guessing a bit because your code isn't quite accurate (it would not generate a null pointer as written as near as I can tell).
EDIT:
You would do the new in the method and the for loop with the assignments could be done inside of the method. I prefer to allocate and initialize in the same place (less confusing) but you can split it up if you needed to.
The problem you are encountering is due to the fact that in Java, parameters to methods are passed by value. What this means, is that every parameter is effectively "copied" into the method, meaning that any assignments you make to the parameters are only visible within the method, and cannot be seen by the caller.
Going by your example, you're passing in a null reference to an array of List<String>'s. This reference is then "copied" into the func() method, and when func then assigns something to this variable, it is only the local variable that is being updated, and not the reference held by your calling code.
Here's some compilable code (based on your example) that demonstrates the problem:
public class Main {
public static void main(String[] args) {
List<String>[] array = null;
fill(array);
System.out.println("In main(): " + array[0].get(0));
}
public static void fill(List<String>[] array) {
array = (List<String>[])new List[10];
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
}
}
The println in fill prints the correct value, because the array variable has been assigned to something within the fill method, however the println in the main method throws an NPE because only the "copy" of the array variable was changed by func, and not the "real" variable.
There are two ways to get around this: either instantiate the array within your calling code, or change the fill() method to return a reference to the array is has created.
Below is the first approach:
public class Main {
public static void main(String[] args) {
List<String>[] array = (List<String>[])new List[10];
fill(array);
System.out.println("In main(): " + array[0].get(0));
}
public static void fill(List<String>[] array) {
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
}
}
You may be wondering why this works, because you're still assigning ArrayList's to the elements of the array, however these objects are visible outside of the calling method. The reason for this is that although the fill method is getting a "copy" of the reference to the array, the reference itself is still referencing the same array object. This means that you can modify the internal state of the array object, and any changes you make will be seen by the caller because it referencing that same object.
Below is the second approach:
public class Main {
public static void main(String[] args) {
List<String>[] array = fill();
System.out.println("In main(): " + array[0].get(0));
}
public static List<String>[] fill() {
List<String>[] array = (List<String>[])new List[10];
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
return array;
}
}
(As an aside, you should generally try to avoid creating arrays of generic collections, a better idea would be to use a list to store the lists themselves. E.g:
List<List<String>> list = new ArrayList<List<String>>();
list.add(new ArrayList<String>());
list.get(0).add("test");
new ArrayList<?>[10] give me incompatible type. However, new ArrayList[10] works for me.
Consider the method declaration:
String.format(String, Object ...)
The Object ... argument is just a reference to an array of Objects. Is there a way to use this method with a reference to an actual Object array? If I pass in an Object array to the ... argument - will the resultant argument value be a two-dimensional array - because an Object[] is itself an Object:
Object[] params = ....; // Make the array (for example based on user-input)
String s = String.format("%S has %.2f euros", params);
So the first component of the array (Which is used in the String.format method), will be an array and he will generate:
[class.getName() + "#" + Integer.toHexString(hashCode())]
and then an error because the array size is 1.
The bold sequence is the real question.
This is a second question: Does a ... array/parameter have a name?
From the docs on varargs:
The three periods after the final
parameter's type indicate that the
final argument may be passed as an
array or as a sequence of arguments.
So you can pass multiple arguments or an array.
The following works just fine:
class VarargTest {
public static void main(String[] args) {
Object[] params = {"x", 1.2345f};
String s = String.format("%s is %.2f", params);
System.out.println(s); // Output is: x is 1.23
}
}
You can just pass an array:
public void foo(String... args) {
}
String args[] = new String[10];
foo(args);
The situation you are describing is going to be fairly rare: most of the time, your varargs items will be Strings, or numbers, or Widgets... it will be unusual for them to be Objects (which could be anything) or arrays.
But if the varargs argument is a bunch of Objects or an array type, then your question does arise: you can pass it a single array and then how will the compiler know whether you meant to pass an array (the one you provided), or an series of 1 item which it should PUT into an array for you?
A quick test shows the answer:
public class TestClass {
public static void main(String[] args) {
Object anObject = new Object();
Object[] anArray = new Object[] {anObject, anObject};
System.out.println("object1 = " + anObject);
System.out.println("array1 = " + anArray);
takesArgs();
takesArgs(anObject, anObject);
takesArgs(anArray); // is this the same as array1?
takesArgs(anArray, anArray);
}
public static void takesArgs(Object... stuff) {
System.out.println("The array was " + stuff);
}
}
The result of executing (your exact numbers will vary:
object1 = java.lang.Object#3e25a5
array1 = [Ljava.lang.Object;#19821f
The array was [Ljava.lang.Object;#addbf1
The array was [Ljava.lang.Object;#42e816
The array was [Ljava.lang.Object;#19821f
The array was [Ljava.lang.Object;#9304b1
So the answer is that in ambiguous cases it treats what you passed as the array instead of creating a new array to wrap it. This makes sense as you could always wrap it in an array yourself if you wanted the other interpretation.