I have a piece of code:
public class Check {
private ArrayList<Integer> diameters; // Array of diameters
public Check(int num) {
diameters = new ArrayList<>(num); // Create an ArrayList object.
for(int i = 0; i < num; i++) { // Initialize the ArrayList.
diameters.add(i, i + 1);
}
}
public ArrayList<Integer> getDiameters() {
return new ArrayList<Integer>(diameters);
}
}
Does the getDiameters()
method return the memory address of diameters ArrayList
(if so, do I need to copy each value individually like I did in the constructor) or does it return a copy of all the integers in the diameters ArrayList
?
Does the return value of getDiameters()
method and the variable diameters
point to the same memory location?
Would the below return statement in the getDiameters()
method be a valid statement without any compromise to security instead of writing "return new ArrayList<Integer>(diameters);
"?
return diameters;
What are the security issues faced, if any, if I write the above statement?
If you do return diameters;
your whole diameters
ArrayList would be mutable, as you provide a link to it directly. That means you can affect it size and content from outside.
When you do new ArrayList<Integer>(diameters)
- you're providing a copy of ArrayList with the copied values (which are copied by a reference, so basically are the same objects as in original collection).
For primitive wrapper like Integer - it's safe, but if you were passing mutable Object within the collection - its change would change the original ArrayList content.
Simple example:
public class Arrayz {
public static void main(String[] args) {
List<Integer> array1 = new ArrayList<>();
array1.add(new Integer(1));
array1.add(new Integer(2));
List<Integer> array2 = new ArrayList<>(array1);
// you can't mutate Integer - it's immutable
Integer first = array2.get(0);
System.out.println(array1);
System.out.println(array2);
List<Nom> array3 = new ArrayList<>();
array3.add(new Nom(1));
array3.add(new Nom(2));
List<Nom> array4 = new ArrayList<>(array3);
Nom third = array4.get(0);
// Nom is muttable - this will affect initial data as the Object itself mutated
third.a = 88;
// this will not - you replaced the Object in copied array only
array4.set(1, new Nom(33));
System.out.println(array3);
System.out.println(array4);
}
}
public class Nom {
public int a;
Nom(int a) {
this.a = a;
}
@Override
public String toString() {
return "" +a;
}
}
//////////// output:
[1, 2] // array1
[1, 2] // array2
[88, 2] // array3
[88, 33] // array4
Generally to protect everything you need to pass an immutable collection with immutable objects.
First can be achieved by using com.google.common.collect.ImmutableList.of
for example.