2

I am slightly confused and hoping someone could shed some light on the matter. I created a function that removes horizontal lines from an image array and returns the image array without any horizontal lines. But when I call this function with my image array it also directly modifies the image array that I passed it. Why does this happen?

Example

int[][] imageArray = ImageToArray();
int[][] _NoLines = RemovedLines(imageArray);

imageArray should still have its lines right?

This is the actual function if anyone is curious:

public int[][] RemovedLines(int[][] _baseImage)
{
    int width = _baseImage[0].length, height = _baseImage.length;   
    
    int white = 0;
    int black = 0;
    
    for (int y = 0; y < height; y++) {
        white = 0;
        black = 0;
        for (int x = 0; x < width; x++) {
            if(_baseImage[y][x] == 0xFFFFFFFF){
                white++;
            }else{
                black++;
            }
        }
        if(black  > white)
        {
            // line detected fist time
            // now get height of line
            int _starts = y;
            _starts++;
            int _end = 0;
            
            for(; _starts < height; _starts++){
                white = 0;
                black = 0;
                for(int _x = 0; _x < width; _x++){
                    
                    if(_baseImage[_starts][_x] == 0xFFFFFFFF){
                        white++;
                    }else{
                        black++;
                    }
                }
                if(white > black){
                    // end of line height
                    _end = _starts;
                    _starts = y;
                    
                    break;
                }
            }
            white = 0;
            black = 0;
            for(;_starts < _end; _starts++){
                for(int line = 0; line < width; line++){
                    if(_baseImage[_starts-1][line] != 0xFF000000 
                        && _baseImage[_starts-2][line] != 0xFF000000
                        || _baseImage[_starts+1][line] != 0xFF000000 
                        && _baseImage[_starts+2][line] != 0xFF000000){
                        _baseImage[_starts][line] =0xFFFFFFFF;
                    }
                    
                }
            }
            y = _end;
        
        }
    }
    return _baseImage;
}
Community
  • 1
  • 1
  • Java always pass by reference. – NaviRamyle Feb 07 '13 at 01:41
  • `"imageArray" should still have its lines right?` ... no ... make new array and modify it – Selvin Feb 07 '13 at 01:43
  • thanks for the quick responses people. soo do i delete this question? –  Feb 07 '13 at 01:45
  • 1
    @Ramyle actually [Java always pass by value](http://stackoverflow.com/questions/40480/is-java-pass-by-reference). – Pshemo Feb 07 '13 at 01:58
  • 1
    @Ramyle: as Pshemo stated, java is always pass by value. I like to refer to it as more of a "pass by value-reference". The value of an object (which an array is a type of object) is the memory location where the data resides. So when you pass the object in, if you modify the contents (by an array item assignment, or some other side effect), it shows in the caller. But if you assigned the parameter as a whole (ie. _baseImage = new int[][]...), that changes is only local, since the caller still has a pointer to the original memory location. – Matt Feb 07 '13 at 05:18

3 Answers3

4

In Java arrays are objects. When an object is passed to a method, the value passed to the method is a copy of its reference. This causes modifications to an object, passed as a parameter to a method, to be made to the reference of the object, which alters the object.

One of the best descriptions of how Java passes by value in relation to primitives and objects that I have encountered is this story on Java Ranch.

Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
1

Arrays in java are objects.
This is like that a pointer to the array is passed, but not the original pointer, but a copy of it.

you modified the content of the array.
You have to create a new Array inside your method. In that copy you can remove the lines.
Then you return that copy.

AlexWien
  • 28,470
  • 6
  • 53
  • 83
1

As others pointed out, arrays are objects and:

Java passes objects as references passed by value

Quoting: Is Java "pass-by-reference" or "pass-by-value"?

Which means that, when you enter the method RemovedLines, _baseImage is a reference that points to the same object as imageArray (two different references pointing to the same object in the heap).

So, your first step should be to create a copy of the original array. Here's how:

int[][] cloneArray = new int[_baseImage.length][];
for (int i = 0; i < cloneArray.length; i++) {
    cloneArray[i] = _baseImage[i].clone();
}

Since _baseImage is a reference passed by value you can even do something like:

_baseImage = cloneArray; 

And from this point on _baseImage inside RemovedLines will be independent of your main imageArray array (each reference will be pointing to a different object in the heap).

But be warned that this will make most Java Developers want to hurt you (It brings back bad memories about SCJP / OCPJP exams). The recommended way to go, as @AlexWien pointed out, is to refactor your code to work over cloneArray and return it.

Community
  • 1
  • 1
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118