2

我有点困惑,希望有人能对此事有所了解。我创建了一个从图像数组中删除水平线并返回没有任何水平线的图像数组的函数。但是当我用我的图像数组调用这个函数时,它也会直接修改我传递给它的图像数组。为什么会这样?

例子

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

imageArray应该还有它的台词吧?

如果有人好奇,这是实际功能:

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;
}
4

3 回答 3

4

在 Java 中,数组是对象。将对象传递给方法时,传递给方法的值是其引用的副本。这会导致对作为参数传递给方法的对象的修改对对象的引用进行,从而改变对象。

我遇到的关于 Java 如何通过与原语和对象相关的值传递的最佳描述之一是 Java Ranch 上的这个故事

于 2013-02-07T01:43:10.597 回答
1

java中的数组是对象。
这就像传递了一个指向数组的指针,但不是原始指针,而是它的副本。

您修改了数组的内容。
您必须在方法中创建一个新数组。在该副本中,您可以删除这些行。
然后你返回那个副本。

于 2013-02-07T01:43:02.847 回答
1

正如其他人指出的那样,数组是对象,并且:

Java 将对象作为按值传递的引用传递

引用:Java 是“按引用传递”还是“按值传递”?

这意味着,当您输入 method 时RemovedLines_baseImage是一个指向同一个对象的imageArray引用(两个不同的引用指向堆中的同一个对象)。

因此,您的第一步应该是创建原始数组的副本。就是这样:

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

由于_baseImage是按值传递的引用,您甚至可以执行以下操作:

_baseImage = cloneArray; 

从这一点开始,_baseImage内部RemovedLines将独立于您的主imageArray数组(每个引用将指向堆中的不同对象)。

但是请注意,这会让大多数 Java 开发人员想要伤害你(它会让人想起关于 SCJP / OCPJP 考试的糟糕回忆)。正如@AlexWien 指出的那样,推荐的方法是重构您的代码以重新处理cloneArray并返回它。

于 2013-02-07T02:08:15.463 回答