Does the array instance variable not relate to the setter method intake? - java

In the main method I make a new object of the DotComClass and set
locationOfShips array to 14 numbers. Then send those values as an
argument over to the setter method (setLocations) in the other class
(see below). My question is why does it allow that pass over without
issue, since I set the max number of elements of the locations
instance variable is 5?
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
DotComClass dotCom = new DotComClass();
int[] locationOfShips = {6,7,8,9,1,2,3,4,4,4,4,5,5,5};
dotCom.setLocations(locationOfShips);
}
}
public class DotComClass {
int [] locations = new int[5]; // is this not related to the locations in the setter?
public void setLocations (int[] locations){
this.locations= locations;
System.out.println(Arrays.toString(locations));
}
}

The locations field is a reference to an array.
This points that reference to a new array of 5 integers.
int [] locations = new int[5]; // is this not related to the locations in the setter?
This re-points that reference to a different array.
this.locations= locations;
The new array has its own size. It's not limited by the size of the array that the reference formerly pointed to.

There is a simple mistake you are making, the variable int [] locations = new int[5]; does not actually contain an array of length 5. It is actually just holding the reference to the array of length 5 somewhere on the heap.
This is exactly what this statement below is also doing,
int[] locationOfShips = {6,7,8,9,1,2,3,4,4,4,4,5,5,5};
so when you are running this.locations= locations;, you are actually saying the variable now refers to the array locationOfShips
If this is not clear i suggest you read about pass by reference good explanation here (Are arrays passed by value or passed by reference in Java?)

Related

How are we able to create an array of any class or interface in Java?

I want to ask a question that confused me more than anything else in java.
When we create an array of references. What actually happens?
E.g I have
class A {
String name;
}
When we create an array like
A[] arr = new A[5];
. What actually happens? Is constructor invoked? If not then what happens internally?
Since arrays are objects how are we able to do this as well e.g
interface G {
void disp();
}
G[] x = new G[5];
Please help me to remove my confusion. It hinders me from many other operations.
When you create an array:
A[] arr = new A[5]
No constructor is called, the only thing that you are doing - is specifying an continuous memory range of references to A.
You can test it by trying to access array at specific index :
A temp = arr[0];
And you'll see that temp variable is null, thich means that its instance is undefined.
Reference isn't an object - it's a reference to the object. It's like a sign that points to somewhere in memory with witch you can find and access the object.
I didn't understood how can you create an instance of interface?
An array of objects is created just like an array of primitive type data items in the following way:
Student[] studentArray = new Student[7];
Following is the definition of this class.
class Student {
int marks;
}
The above statement creates the array which can hold references to seven Student objects. It doesn't create the Student objects themselves. They have to be created separately using the constructor of the Student class. The studentArray contains seven memory spaces in which the address of seven Student objects may be stored. If we try to access the Student objects even before creating them, run time errors would occur. For instance, the following statement throws a NullPointerException during runtime which indicates that studentArray[0] isn't yet pointing to a Student object.
studentArray[0].marks = 100;
The Student objects have to be instantiated using the constructor of the Student class and their references should be assigned to the array elements in the following way.
studentArray[0] = new Student();
In this way, we create the other Student objects also. If each of the Student objects have to be created using a different constructor, we use a statement similar to the above several times. However, in this particular case, we may use a for loop since all Student objects are created with the same default constructor.
for ( int i=0; i<studentArray.length; i++) {
studentArray[i]=new Student();
}
The above for loop creates seven Student objects and assigns their reference to the array elements. Now, a statement like the following would be valid.
studentArray[0].marks=100;
Enhanced for loops find a better application here as we not only get the Student object but also we are capable of modifying it. This is because of the fact that Student is a reference type. Therefore the variable in the header of the enhanced for loop would be storing a reference to the Student object and not a copy of the Student object which was the case when primitive type variables like int were used as array elements.
for ( Student x : studentArray ) {
x.marks = s.nextInt(); // s is a Scanner object
}
Recall that we were not able to assign to the array elements in a similar way when the array was of type int.
Moreover, in the case of array of objects, when we pass an array element to a method, the object is susceptible to changes. This is because the element being passed is also a reference type item. This differs from the situation when we have an int array. Following illustrates this concept.
public static void main(String[] args) {
Student[] studentArray = new Student[7];
studentArray[0] = new Student();
studentArray[0].marks = 99;
System.out.println(studentArray[0].marks); // prints 99
modify(studentArray[0]);
System.out.println(studentArray[0].marks); // prints 100 and not 99
// code
}
public static void modify(Student s) {
s.marks = 100;
}
Compare the output with the one when the array was of type int[].
Processing an array of objects is much similar to the processing of an array of primitive type. the only thing to be kept in mind is the possibility of NullPointerException being thrown during run time and also remembering that the array elements themselves are reference types, which brings subtle differences from the case when they are passed as parameters. Moreover, an enhanced for loop may be used to initialise the array elements.
Refrence

Using an existing array in another class

Let's change the way I am asking the question. For constructing an object in a class, we can also use some other variables. Consider this example:
public class Foo {
int X1;
int X2;
public Foo(int a) {
int[] array=new int[4];
// ...
}
}
If we create 2 objects of this class, we will have 2 variables per object and totally the memory will be occupied for 4 integer variables. My concern is the memory dedicated to the integer array defined inside the constructor. How the memory will be assigned when creating several objects?
Thanks,
To answer your first question, yes. If you create an array in the main method of one class, then you create the same array again in the constructor of another class, then there will be two copies of that array in memory. More importantly, if you later modify one copy, the other copy will not be modified.
The best way to solve your problem is to pass the array into the constructor as a parameter. Then, you'll be able to access (and even modify) elements of the original array. For example:
public class Driver{
public static void Main(String[] args){
int[] array = {1, 2, 3};
CustomObject otherObject = new CustomObject(array);
}
}
//And, in a different file....
public class CustomObject{
public CustomObject(int[] array){
int x = array[0];
//etc..
}
}
If you have two references to the same object there won't be any useless memory usage.
For better understand how it works, look at the difference between stack and heap memory in Java
(Basically, your array in main method and the array defined in the class's constructor point to the same memory area)

Advance for reference variables?

I am trying to understand the difference between Object with primitive variables when using them as parameters in a method.
There are some examples using reference variables:
public class Test1 {
public static void main(String[] args) {
int[] value = {1};
modify(value);
System.out.println(value[0]);
}
public static void modify(int[] v) {
v[0] = 5;
}
}
result: 5
public class Test2 {
public static void main(String agrs[]) {
Integer j = new Integer(1);
refer(j);
System.out.println(j.intValue());
}
public static void refer(Integer i) {
i = new Integer(2);
System.out.println(i.intValue());
}
}
result: 2 | 1
So what is different in here?
In java array is primitive type.and Integer is Object type.
For primitives it is pass by value the actual value (e.g. 3)
For Objects you pass by value the reference to the object.
In first example,
you are changing value in array.
while in other example ,
you are changing reference of i to other memory location where object value is 2.
when returning back to main function, as you are not returning value. its reference scope limited to "refer" method only.
Recall that the array references are passed by value. The array itself is an object, and that's not passed at all (That means that if you pass an array as an argument, your'e actually passing its memory address location).
In modify() method, you're assigning 5 to the first place in the array, hence, changing the array's value. So when you print the result, you get: 5 because the value has been changed.
In the second case, you're creating a new Object of type Integer locally. i will have the same value when you exit the method refer(). Inside it you print 2, then you print i, which is 1 and hence change doesn't reflect.
v[0] = 5, is like saying Get 0th element of current v's reference and make it 5.
i = new Integer(2), is like saying change i to 2's Integer object reference
In one case you are changing the internal values via the reference and in latter you are changing the reference itself.
The difference here is that they are different.
In your first example you are passing the argument to another method, which is modifying one of its elements, which is visible at the caller. In the second case you are assigning the variable to a new value, which isn't visible at the caller, because Java has pass-by-value semantics.
NB 'Primary variable' has no meaning in Java.
I don't know what the word 'advance' in your title has to do with anything.

Why when I pass an array, it changes value in the method? Amazing [duplicate]

This question already has answers here:
Changing array in method changes array outside [duplicate]
(2 answers)
Closed 3 years ago.
public class Test {
public static void main(String[] args) {
int[] arr = new int[5];
arr[0] = 1;
method(arr);
System.out.println(arr[0]);
}
private static void method(int[] array)
{
array[0] = 2;
}
}
After invoking method, arr[0] becomes 2. Why is that!?
You can call set methods on objects passed to a method. Java is pass by value, which means that you can't replace an object in a method, though you can call set methods on an object.
If Java were pass by reference, this would pass:
public class Test {
public static void main(String[] args) {
Test test = new Test();
int j = 0;
test.setToOne(j);
assert j == 1;
}
public void setToOne(int i) {
i = 1;
}
}
Java is Pass-by-Value, Dammit! http://javadude.com/articles/passbyvalue.htm
This is because Java uses Call by Object-Sharing* (for non-primitive types) when passing arguments to method.
When you pass an object -- including arrays -- you pass the object itself. A copy is not created.
If you mutate the object in one place, such as in the called method, you mutate the object everywhere! (Because an object is itself :-)
Here is the code above, annotated:
public static void main(String[] args)
{
int[] arr = new int[5]; // create an array object. let's call it JIM.
// arr evaluates to the object JIM, so sets JIM[0] = 1
arr[0] = 1;
System.out.println(arr[0]); // 1
method(arr); // fixed typo :-)
// arr still evalutes to JIM
// so this will print 2, as we "mutated" JIM in method called above
System.out.println(arr[0]); // 2
}
private static void method(int[] array)
{
// array evaluates to the object JIM, so sets JIM[0] = 2
// it is the same JIM object
array[0] = 2;
}
Happy coding.
*Primitive values always have call-by-value semantics -- that is, a copy is effectively created. Since all primitive values are immutable this does not create a conflict.
Also, as Brian Roach points out, the JVM only implements call-by-value internally: the call-by-object-sharing semantics discussed above are implemented by passing the value of the reference for a given object. As noted in the linked wikipedia article, the specific terms used to describe this behavior differ by programming community.
Additional:
Pass by value or Pass by reference in Java? -- see aioobes answer and how it relates with Brian Roachs comments. And aioobe again: Does array changes in method?
Make copy of array Java -- note this only creates a "shallow" copy.
Because that's exactly what you're telling it to do. Java passes first by value, then by reference. You're passing in the array, but any modifications you make to that array will be reflected on any other accesses to that array.
A quick example for thought:
If within method you did array = null, no change would be visible from main - as you would be changing the local value of array without modifying anything on the reference.
Because when you are passing argument like int/double/char etc. they are the primitive data types and they are call by value - meaning their values are copied to a local variable in this method (that has the same name as the names in your argument) and changes made to them are only changes made to these local var -> does not affect your primitive type variables outside the method
however an array or any object data type is called by reference -> the argument pass their address(reference) to method. that way, you still have a local variable named by them which has the reference. You can change it to reference another array or anything. but when it is referencing an array, you can use it to set the value of the array. what it does is accessing the address it is referencing and change the content of the referenced place
method(arr[0]);
I think that's supposed to be
method(arr);
But anyway the value passed as argument to the method is the reference to the array and the local variable arr in the method is referencing the same array. So, within the method you are making changes to the same array.
Java is pass by value. What confuses people is that the 'value' of a variable that refers to an object allocated on the heap is a reference, so when you pass that, you pass the reference 'by value' and therefore it refers to the same object on the heap. Which means it doesn't matter from where you modify the referent; you're modifying the same thing.

Is it safe to re-use variables inside a method?

I have an array of type string which I want to re-use inside a method.
I need to pass it to a function which returns a subset of the elements of array passed. To capture the returned array from function, should I declare a new string array or can I safely re-use same array that was holding the unfiltered array to hold filtered array ??
Also clarify that, when I pass a variable like array to a function does it creates a new space for the array in the heap each time I pass it as parameter to further functions or just it uses the same space in the heap & just passes the reference? I guess in case of array it passes just the reference but in case of simple variables it allocates new space on stack, right?
EDIT: Thanks you all for the great answers and explanations!!
Please also clarify whether that if I am reusing the array, would I be required to set the null at the position when I end the subset of array ? (Actually the subset of my array is not directly calculated from the array but some other calulations, so I would be required to manually set the null otherwise the older elements of the list would be visible, right??)
when I pass a variable like array to a function does it creates a new space for the array in the heap each time I pass it as parameter to further functions or just it uses the same space in the heap & just passes the reference
Java is entirely pass by value, but with arrays and object types, the value being passed is a reference (pointer) to the actual object, which is not duplicated. So when you pass an array into a function, only the reference to the array is copied; the array itself isn't. That's why if a function modifies the contents of an array, the code calling the function sees the modifications.
Example:
// A method that changes the first entry in an array
void changeArray(String[] theArray) {
theArray[0] = "Updated";
}
// A method that uses the above
void someMethod() {
String[] foo = new String[3];
foo[0] = "Original 0";
foo[1] = "Original 1";
foo[2] = "Original 2";
this.changeArray(foo); // `changeArray` receives a *copy* of the reference
// held in `foo`; both references point to the same
// array
System.out.println(foo[0]); // Prints "Updated"
}
Passing a reference into a method is exactly like assigning it to another reference variable:
String[] foo = new String[3]; // Create a new aaray, assign reference to `foo` variable
String[] bar = foo; // Copy the reference into `bar` as well
foo[0] = "Hi there"; // Use the reference in `foo` to assign to the first element
System.out.println(bar[0]); // Use the reference in `bar`, prints "Hi there"
Essentially, references are values (numbers) that tell the JVM where the data for an object is. So even when we copy a reference (because Java is entirely pass-by-value, the value of the reference is passed to the function), it still points to the same memory as the original.
Since the reference is passed into the function by value, the function can't change the calling code's reference:
// A method that assigns a new reference; the calling code sees no change
void changeReference(String[] theArray) {
theArray = new String[1]; // Now we're not using the caller's object anymore
theArray[0] = "I was changed";
}
// A method that uses the above
void someMethod() {
String[] foo = new String[3];
foo[0] = "Original 0";
foo[1] = "Original 1";
foo[2] = "Original 2";
this.changeReference(foo);
System.out.println(foo[0]); // Prints "Original 0", our reference wasn't changed
}
You'll note that this is exactly how primitives are treated:
void whatever(int a) {
a = 5;
}
void someMethod() {
int foo;
foo = 3;
whatever(foo);
System.out.println(foo); // Prints 3, of course, not 5
}
...and in fact, object references (as opposed to objects) are primitives.
...should I declare a new string array or can I safely re-use same array that was holding the unfiltered array to hold filtered array
You can safely re-use it if that's appropriate within the scope of your function. It may be more appropriate to declare a new variable (e.g., filteredThingy), but that's a matter of style and will depend on the situation.
You probably can by it is very bad style and is very error prone and is very unsafe for future modifications.
Here is the example.
public void foo(String[] args) {
// do something with array.
args = new String[] {"a", "b"}; // reuse of the array.
// more code.
for (Sring s : args) {
// what will this loop get"?
// The answer is: a, b
// but will you remember this fact in a month if "more code" above is 50 lines long?
}
}
Passing objects is essentially passing references. E.g., your array will only exist in one place in memory when passing it between functions. Here's a runnable example illustrating that.
If you like you can reuse the same array in your routine. Note that changes made to that array will be visible to all objects sharing the same reference to that array. If that's not desirable then you must declare a new array.
String parentArray = {"S","B","R"};
// no need to use new operator to hold subSetArray.
String subSetArray = returnSubSet(parent);
public String[] returnSubSet(String[] _parent)
{
return Arrays.copyOfRange(_parent,1,2);
}
, when I pass a variable like array to
a function does it creates a new space
for the array in the heap each time I
pass it as parameter to further
functions or just it uses the same
space in the heap & just passes the
reference?
Answer
1. Object in Java are Pass by reference by value
2. when you pass an array to a function , a _parent variable will be created in stack and it points to the same Array Object in heap.
UPDATES: Primitive example
int global_scope_variable=10;
setValue(global_scope_variable);
public void setValue(int val)
{
// val is visible only within this method.
System.out.println(val); // output is 10
val=20;
System.out.println(val); // output is 20
System.out.println(global_scope_variable); // output is 10
}

Categories

Resources