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.
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 was doing some exercises on arrays, and I was prompted to return a reference to an array after copying it element by element. What does this exactly mean?
My code is the following:
public static int[] cloneArray(int array[])
{
int[] arraycopy = new int[array.length];
for(int i = 0; i < array.length; i++)
{
arraycopy[i] = array[i];
}
return arraycopy;
}
I don't know what I should be returning though as a "reference": should I return an array of ints or an int? Whenever I try to print the array, I get a weird combination of characters and numbers (unless I invoke Arrays.toString()).
"Return a reference to an array" just means "return an array".
Java only returns values, which are either primitives or object references (ie for objects, the value is a reference).
Although Java is based on C, it doesn't sully itself with pointers etc like C does.
In Java, arrays and objects do not act like primitive types such as int. Consider the following code:
public class MyClass {
public static int method1(int ar[]) {
int x = ar[1];
ar[1] = 3;
return x;
}
}
Now suppose that somewhere else, the follow code is executed:
int abcd[] = new int[3];
abcd[0] = 0;
abcd[1] = 1;
abcd[2] = 2;
int d = MyClass.method1(abcd);
System.out.println(abcd[1]);
What would be printed? It's not 1, but 3. This is because the method was not given the data in the array, it was told the location of the array. In other words, it was passed a reference. Because it was using a reference, changing the value of an array index changed its value in the code that called it. This would not have happened if method1 had taken an int as an argument.
Basically, in Java, methods do not accept arrays as arguments or return arrays. They only use references to arrays. The same goes for objects (except for Strings, which are passed by value).
In Java, Objects are only accessed by reference. Just return the Array object.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I copy an object in Java?
How can I initialize an object (say A) in java and set its initial member values equal to a second object (say B). After initialization I want to modify the members of A without modifying the members of B. So at initialization of A I only want to copy the data of B. How is this done in a nice way??
You could implement and use clone
MyClass b = new MyClass();
MyClass a = b.clone();
Note: some classes are not Cloneable, or have broken implementations. e.g. only have a shallow copy when they should be a deep copy.
If the class is Serializable you can serialize it and deserialize it in memory. Not exactly nice but it works.
Or you could create your own "copy" constructor.
One possible solution for that would be implement clone method on your class and use clone as follows:
MyClass a = new MyClass();
MyClass b = a;
You will notice that clone() isn't really a public method, so your will need to expose it. Additionally you need to tell Java that your object is Cloneable (this is done making your class implement Cloneable). The following code ilustrate it:
public class MyClass implements Cloneable {
#Override
protected MyClass clone() throws CloneNotSupportedException {
return (MyClass)super.clone();
}
}
That all depends on the type of the members. I'll give an Example:
class A
{
public float value;
public int[] anArray;
public A(B b)
{
//primitive may be assigned directly.
this.value = b.value;
// other types different approaches:
//copy the contents of the array
this.anArray = new int[b.anArray.length];
System.arraycopy(b.anArray, 0, this.anArray, 0, b.anArray.length);
}
}
class B
{
float value;
int[] anArray;
public B(int size)
{
this.value = 3f;
this.anArray = new int[size];
for (int i = size - 1; i >= 0; i--)
{
this.anArray[i] = i * 10;
}
}
}
B b = new B(5);
A a = new A(b);
Cloning is a straightforward option for copying. If you ever want to do something where you need more control, create your own method that performs your copy exactly how you need it:
public MyType copy()
{
MyType a = new MyType();
// Initialize how you need to here, use the object this was called from if you'd like
a.property = this.property;
// etc.
return a;
}
This gives you more direct control, but takes more time to code. If clone will suit your purposes, stick to that.
EDIT: I am going to give an example based on your comments on this answer.
Let us assume we have the following types:
TypeA: has the following member variables
int number = 5; // Default value built in by constructor.
int letter = 'x'; // Value is 'a' when constructed but has been changed.
ArrayList<TypeB> list = {b1, b2, b3} // All are initialized.
TypeB: has the following member variables
double decimal = 5.32
TypeC someObject = ...
TypeC: has some stuff, but we are going to ignore it.
Now, When we want to copy TypeA, we must do the following:
Copy over the number and character directly as they are value types.
Copy over a reference to the ArrayList which contains a reference to some TypeBs.
Luckily those are easy steps.
int copyNumber = this.number;
char copyChar = this.letter;
ArrayList<TypeB> copyList = this.list;
return new TypeA(copyNumber, copyChar, copyList);
Now that assumes a particular constructor that takes those three arguments, but hopefully you get the idea.
It would get tricky if you wanted to just get values, not references to all of the TypeBs in the ArrayList. You would have to loop through the ArrayList and create new TypeBs that copied all of ITS values (double and TypeC objects as either references or values...)
In short, what you want is an easier copy to perform. Simple assignment operators copy values with primitive types and references with Objects.
I need to convert C code to Java.
The minimal C code is:
void changeX(int *x)
{
*x=5;
}
changeX is called in function B as:
void B()
{
int k= 2;
changeX((int*) &k);
}
The problem while converting it into Java is that x is not a class member so i cannot use this. How can i convert such code to Java?
Assuming you're really asking, "Can I use pass-by-reference in Java" (which that C code isn't using, but is emulating with pointers, which also aren't supported in Java) the answer is no.
Options:
Pass in a reference to an object which does contain a field you can change
(Ugly, but equivalent to the above in some senses) Pass in an array of size 1 constructed using the local variable, mutate the variable in the method, and then set the local variable again based on the array contents afterwards
Return the new value and assign it that way
Change your design so you don't need this
The last two of these options are the nicest ones. If you could give more information about the bigger picture - why you think you want to do this - that would be helpful.
Use one-element array reference:
void changeX(int[] x) {
// do not forget about checks
x[0] = 5;
}
void test() {
int[] x = {0};
changeX(x);
}
Being a primitive, and not a class member, you cannot pass the reference to another method. Use a class member instead.
You should return the new value of x,the method should as follow:
private int changeX(int x){
return 5;
}
You existing C code is incorrect:
void B()
{
int k= 2;
// you are not passing address of variable k but instead
// you are passing k (which is 2) as the address whose location needs
// to be changed. So you are writing to address 2 which you don't own.
changeX((int*) k);
}
What you need is:
changeX(&k);
Now this is changing the value of a variable by passing it by address. Now such a thing is not possible in Java which always uses pass by value. But you can get similar effect by enclosing the int variable inside an Integer object or an integer array (also an object) and pass the object by value.
Simply put Java has no equivalent to a pointer to a basic type - in order to achieve this you need a reference int type something like
class RefInt {
public int Value;
RefInt(int x) { Value=x; }
}
And you pass this in the same context and it works like so:
RefInt X=new RefInt(3)
ChangeX(X);
Obviously in this context simply changing the return value to type int and assigning it would be better but that doesn't solve your general problem.
Option1:
Put the int variable in a wrapper class. Pass that the method. In the method you can change the value in wrapper instance.
Option2:
Make changeX() return int and replace all changeX(k) with k = changeX(k).
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.