-1

I'm relatively new to Java, and I just learned this

import java.util.Arrays;

public class Foo {

  private int[][] foo;

  public Foo(int[][] arr) {
    this.foo = arr;
  }

  @Override
  public String toString() {
    return Arrays.deepToString(this.foo).replace("],", "],\n");
  }
  
  public static void main(String[] args) {
    
    int[][] p = { { 0, 0 }, { 0, 0 } };
    
    Foo g = new Foo(p.clone()); // doesn't work with p nor p.clone()
    System.out.println(g);
    
    p[0][0] = 1;
    
    System.out.println(g);
    
  }

}

Here I create an object with a reference to another object, and I can alter the object from the outside since I have the reference to the thing I just passed as an argument to the constructor.

This, although I understand why it happens, seems counterintuitive to me. If I save something as an attribute of an object I expect the object to have a “private” copy not accessible outside.

And I tried with .clone() and doesn't solve it. So the question is...

How is this usually done? Do I need to write a few for loops inside the constructor to get every value out of the argument?

 (Or is this a non-issue?)

This last part of the question is important, may be this is a non-issue. Or do people do “something” (a few loops to get a deep clone)?

Community
  • 1
  • 1
Manuel
  • 301
  • 2
  • 11
  • 2
    What doesn't work? What is this "This" in your question? – jhamon Feb 04 '19 at 15:06
  • well "counterintuitive" is relative. For arrays most languages work this way. Otherwise you'd get a huge overhead. For Java Objects and Arrays the references are passed. If you want a copy you'll need to create one. – kai Feb 04 '19 at 15:12
  • @kai My question is if this is an issue (or may be not) and how is usually done the setting of a private attribute from a reference (do people deepcopy, or assume there won't be any problem outside)? – Manuel Feb 04 '19 at 15:17
  • @jhamon I edited. I mean if this is usually how it's thone `this.foo = arr` or is it usually done with a deep copy? – Manuel Feb 04 '19 at 15:17
  • 1
    @Manuel it is "usually" not done if not necessary. For the how to do a deep copy see the links in other comments(good explainations!). – kai Feb 04 '19 at 15:25
  • @kai Yep, I know how to do a deepcopy, although I don't know if there's a general way of doing it for an array of n-dimension (or would I need to define such a method). But thanks, that was the answer I seeked. – Manuel Feb 04 '19 at 15:30
  • 1
    @Manuel see 2nd comment from Spara. – kai Feb 04 '19 at 15:32

1 Answers1

3

The problem here is that java doesn't really have 2-D arrays. This:

int[][] x;

is an array of int arrays. It is not a 2D int array, though of course an array of int arrays does feel a lot like a 2D array. For most intents and purposes it iS a 2D int array, unless it isn't, and with clone, it isn't. The clone() impl of an array makes a new array and just copies each and every value, verbatim, into the new array. Which means that your array of int arrays is cloned, but the inner int arrays are not.

When treating int[][] as 'this is a 2D array', yeah, that is unintuitive. When treating int[][] as 'an array of int arrays', it is quite intuitive. You wouldn't expect an array of arraylists, when cloned, to also clone each individual arraylist either.

Soo.. how do you deep-clone an array of arrays (of arrays of arrays)? See How do I do a deep copy of a 2d array in Java? for lots of options :)

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • The title of that linked question should be changed, since there are options to deep copy arrays of n-dimensions. Could you answer also if this is usually a non-issue, or how do people usually assign arrays to attributes? – Manuel Feb 04 '19 at 15:42
  • 1
    Well, either [A] the array is small and you either deep-copy it around or more likely find a more palatable data type than arrays – a data type which is immutable, obviating the need for defensive copies. (The right datatype depends on what the array is representing. If it is representing a game board, perhaps make a class called Board. It has an int[][] internally, but you can't modify it, so you can pass around copies of Board at will). Alternatively, [B] it is a rather large array, in which case you really don't want to make defensive copies. – rzwitserloot Feb 04 '19 at 15:51