I'm doing a task for a course in Java programming and I'm not sure how the following thing is working? The method below takes the value from an array and a integer. The integer should be added to the array and then be used outside the method in other methods and so on, but how could this work when the method has no return for the new content of the array? There is a void in the method? Have I missed something? Preciate some help? Is there something about pointers?
public static void makeTransaction(int[] trans, int amount);
Arrays in Java are objects. If you modify the trans array inside the method, the changes will be reflected outside of it1. Eg:
public static void modify(int[] arr)
{
arr[0] = 10;
}
public static void main(...)
{
int x = {1, 2, 3};
System.out.println(x[0]); // prints 1
modify(x);
System.out.println(x[0]); // now it prints 10
}
Note that native arrays can't be dynamically resized in Java. You will have to use something like ArrayList if you need to do that. Alternatively you can change the return type to int[] and return a new array with the new element "appended" to the old array:
public static int[] makeTransaction(int[] trans, int amount)
{
int[] new_trans = Arrays.copyOf(trans, trans.length + 1);
new_trans[trans.length] = amount;
return new_trans;
}
1 It is also worth noting that as objects, array references are passed by value, so the following code has no effect whatsoever outside of the method:
public void no_change(int[] arr)
{
arr = new int[arr.length];
}
You can't add anything to an array. Java arrays have a fixed length. So indeed, what you want to do is impossible. You might make the method return an int[] array, but it would be a whole new array, containing all the elements of the initial one + the amount passed as argument.
If you want to add something to an array-like structure, use an ArrayList<Integer>.
Do you have to keep the method signature as is?
Also, can you be a bit more specific. When you say "the integer should be added to the array", are you referring to the amount argument? If so, then how is that amount added? Do we place it somewhere in the array or is it placed at the end, thus extending the array's length?
As far as pointers go, Java's pointers are implicit, so if you don't have a strong enough knowledge of the language, then it might not be so clear to you. Anyways, I believe that Java methods usually will pass objects by reference, and primitives by value. But, even that isn't entirely true. If you were to assign your object argument to new object, when the method terminates, the variable that you passed to the method is the same after the method executed as it was before. But, if you were to change the argument's member attributes, then when the method terminated those attributes values will be the same as they were inside of the method.
Anyways, back to your question, I believe that will work because an array is an object. So, if you were to do the following:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
}
// static int i;
/**
* #param args
*/
public static void main(String[] args)
{
int[] trans = {0,1,3};
makeTransaction(trans, 10);
for(int i = 0; i<trans.length; i++)
{
System.out.println(trans[i]);
}
}
The output of the array will be:
10
1
3
But, watch this. What if I decided to implement makeTransaction like so:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
trans = new int[3];
}
What do you think that the output will be? Will it be set to all zero's or will be the same as it was before? The answer is that the output will be the same as it was before. This ties in to what I was saying earlier.
I might've assigned that pointer to a new object in memory, but your copy of the pointer inside of the main method remains the same. It still points to the same place in memory as it did before. When the makeTransaction method terminates, the new int[3] object that I created inside of it is available for garbage collection. The original array remains intact. So, when people say that Java passes objects by reference, it's really more like passing objects' references by value.
Related
The following code:
public static void main(String[] args) {
int first = 1;
int second = 2;
sum(first,second);
System.out.println(sum);
}
public static int sum(int a, int b){
int sum = a+b;
return sum;
}}
will return error and I need to write
int x = sum(first,second);
System.out.println(sum);
and define that method as integer x and print x.
But for array,
public static ArrayList<String> removeLast(ArrayList<String> list) {
//code
return list;
}
public static void main(String[] args) {
//code
removeLast(persons);
System.out.println(persons);
}
will print the returned value of array without defining as another array as the was with the previous one.
I am sorry if the question has already been asked as I couldn't find it. And I am just learning Java.
Arrays are passed by (value of) reference, therefore, any change that happens to the array inside the method, will actually change the array passed in to it. On the other hand ints are passed by value. Change an int inside a method, and it won't change the int passed into the method.
For this reason, the return statement in your array method is completely unnecessary. Your code will still change the array, even if you omit the return statement.
But there's another misconception that needs to be pointed out: when you sum two ints, you are creating a new value in memory, which exists as long as the method is executed. When the sum method is done, the sum int doesn't exist anymore. To retain its value, you need to return it from within the method, and assign it to a variable where you call the code.
Because Java is pass by value, but the value of reference types (including arrays) is a reference to the Object (in this case, a List). You might use a variadic function and (in Java 8+) an IntStream to implement it like
public static int sum(int... arr) {
return IntStream.of(arr).sum();
}
Then you can call sum with as many (or few) int arguments as you like.
Will print the returned value of array without defining as another
array as the was with the previous one ?
Whatever #yeedle mentioned above is correct, but one point to add as below:
ArrayList class (actual type of persons object) has overridden the toString() method such that it
could print the array details when you invoke
System.out.println(persons);.
You need to know that for your objects (created for your custom
classes like Product, Employee, etc..), you need to override
toString() method (inherited from java.lang.Object) to print the
values like how you wanted, otherwise simply using
System.out.println(object); will print the hashcode of the
object (like #HA5431 etc..).
You can look here and here
I had to make a program which was able to print symbols based off an array with numbers, with the numbers corresponding to the amount of symbols to print.
I got this to work; here is the code:
class printChart {
int[] values;
void barChart(int[] values){
for (int i=0;i<values.length;i++){
int number = values[i];
for (int j=0;j<number;j++){
System.out.print("*");
}
System.out.println();
}
}
void demo(){
barChart(new int[] {2,5,0,4,3});
}
public static void main(String[] args){
new printChart().demo();
}
}
My question is as follows: How does Java know that the {2,5,0,4,3} array should be assigned to the variable values? I'm assuming it's because I set void barChart to pass along int[] values, but I'd like to know more about the inner workings and what's going on exactly.
In Java, everything is pass-by-value and it is also important to know what the value is.
This method
void demo(){
barChart(new int[] {2,5,0,4,3});
}
Do the same as this one
void demo(){
int[] arr = new int[] {2,5,0,4,3};
barChart(arr);
}
In the first one, there is created new array with 2,5,0,4,3 values and its reference is copied to parameter values in barChart method.
In second one, there is created new array with 2,5,0,4,3 values and its reference is copied to variable arr. Then the value of arr (which is reference to array) is copied to parameter values in barChart method.
And this is how it works and why barChart method knows the values.
Also good point by Ćukasz, the second line does not do anything in your program, therefore you can change this :
class printChart {
int[] values;
void barChart(int[] values){
to this
class printChart {
void barChart(int[] values){
I'm not so sure what your question is, but let me tell you bit what you've done.
You've implemented a method(function) named void barChart(int[] value)
To run this method you must need to pass a one dimensional Array of Integer values to it.
Now comes the interesting part.
You've created a class Variable int[] values; in code line 2.
Also you've have created the lokal variable "value" in the method void barChart(int[] value).
What you've done is called overshadowing. The method "barChart()" only uses the lokal value which is passed to it when it is called.
You never used the class variable once, hence you could delete it.
Now if you want to use the class variable you could either:
a) Change the name of the variable (class or local)
b) In the method "barChart" write a this.value instead of just value. This will ensure that you are using the class variable and not the local one.
public class foo {
private int a[];
private int b;
public foo(){
a = new int[] {1,2};
b= 3;
}
public int[] getA(){
return this.a;
}
public int getB(){
return this.b;
}
I noticed that it's possible to change a value of A by accessing the object like this:
foo f = new foo();
f.getA()[0] = 5; // f.a[0] changes to 5
but it isn't possible to do something like:
f.getB = 5; // gives error
f.getA() = new int[]{2,3}; //gives error
can someone explain me how this works, and how to prevent the user from changing the value of an array cell?
Thanks in advance.
In Java, array is a reference type, which means that the value of an array expression is a reference to the actual array.
The return value of getA() is, therefore, a reference to the private array inside your object. This breaks encapsulation: you give access to your object's internals.
You can avoid this by either returning a reference to a copy of your internal array, or by providing a different API which only returns individual elements, say a method getA(int index).
f.get(A) returns a reference to an array. You can access that array the way you access any array, and assign values to its elements with f.get(A)[i]=... (though it makes more sense to store the returned array in a variable, which would let you access that array multiple times, without having to call f.get(A) each time).
You can't, however, assign anything f.get(A) via f.get(A)=.., since a method call is not a valid left side of an assignment operator. For all you know, a call to f.get(A) may generate a new array that is not referred to by a member of the foo class, so assigning f.get(A)= new int[5]; would make no sense, since there would be no variable in which to store the new array.
The same explanation applies to f.getB() = 5;.
Instead of giving away the array, to allow the caller to do what they like with it you can use an indexed getter
public int getA(int n){
return this.a[n];
}
public void setA(int n, int x) {
this.a[n] = x;
}
Now, the caller has no access to the array and cannot change it without you knowing.
I am having a little trouble understanding the concept of final in Java.
I have a class that follows:
public class MyClass
{
private int[][] myArray; // intended to be changed
private final int[][] MYARRAY_ORIGINAL; // intended to be unchangable
public MyClass(int[][] array)
{
myArray = array;
MYARRAY_ORIGINAL = array;
}
}
I was under the understanding that final would make MYARRAY_ORIGINAL read only. But I have tried editing myArray, and it edits MYARRAY_ORIGINAL as well. My question is, in this context, what exactly does final do? And for extra credit, how can I copy the array passed through the constructor into MYARRAY_ORIGINAL so that I can have 2 arrays, one to edit, and one that will remain preserved?
Your final MYARRAY_ORIGINAL is indeed read only: you can't assign a new value to the MYARRAY_ORIGINAL reference in other side than class constructor or attribute declaration:
public void someMethod() {
//it won't compile
MYARRAY_ORIGINAL = new int[X][];
}
The values inside the array are not final. Those values can change anytime in the code.
public void anotherMethod() {
MYARRAY_ORIGINAL[0][0] = 25;
//later in the code...
MYARRAY_ORIGINAL[0][0] = 30; //it works!
}
If you indeed need a List of final elements, in other words, a List whose elements can't be modified, you can use Collections.unmodifiableList:
List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));
The last piece of code was taken from here: Immutable array in Java
In case of Objects, final makes reference can't be changed, but object state can be changed.
That is the reason why you are able to change values of final MYARRAY_ORIGINAL
MYARRAY_ORIGINAL is indeed read only variable. Your array reference can not be assigned a new value nor for their length of the arrays can be changed. A final variables initialization can be deferred till the constructors is called. If one tries to modify the reference of the final variable, compiler will throw an error message. But what is possible is, one can edit the elements of the MYARRAY_ORIGINAL and of the myArray i.e one can change the state of the object assigned to a final variable. For example
Class A {
final int[] array;
public A() {
array = new int[10] // deferred initialization of a final variable
array[0] = 10;
}
public void method() {
array[0] = 3; // it is allowed
array = new int[20] // not allowed and compiler will throw an error
}
}
To understand more on final please take a look at Java Language Specification on final variable.
Final does not mean 'read-only' per se, but more so "safe publication' for other threads than the one to which it is defined. Another aim of 'final' is that it ensures the latest object available in a multi-thread environment.
Secondly, if you define something as "final", for example:
private final int[][] MYARRAY_ORIGINAL;
The reference is "final", but not the object itself. A much better way to understand it would be this:
public static final List myList = new ArrayList();
Now I can access myList from any other threads - I can modify it (add to it); but I cannot
(a) Declare it again - myList = new ArrayList();
(b) Assign it another list - myList = anotherList;
The context for final I would see best, in a multiple-thread scenario.
Bonus: to answer your question, you cannot make a 'readonly' array, you will have to manage that yourself (as final, only maintains 'read-only' to reference not object)
You can use the method System.arraycopy to make a copy of the array as follows -
int[][] source = {{1,2},{3,4}};
int[][] copy = new int[source.length][];
System.arraycopy(source, 0, copy, 0, source.length);
Also, you some problem with your code regarding what you are trying to do. If you look at the constructor
public MyClass(int[][] array) { //something else passes the array
myArray = array;
MYARRAY_ORIGINAL = array; // you are just keeping a reference to it can be modified from outside
}
If you really want nobody to modify the values in that array MYARRAY_ORIGINAL, you should make a copy of the source array that comes comes from outside.
public MyClass(int[][] array) {
myArray = array; //make a copy here also if you don't want to edit the argument array
MYARRAY_ORIGINAL = new int[array.length][];
System.arraycopy(array, 0, MYARRAY_ORIGINAL, 0, array.length);
}
Now you shouldn't have to worry about the array's being modified from outside.
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.