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 がどのように値渡しをするかについての最も良い説明の 1 つは、Java Ranch に関するこの話です。

于 2013-02-07T01:43:10.597 に答える
1

Java の配列はオブジェクトです。
これは、配列へのポインターが渡されるようなものですが、元のポインターではなく、そのコピーが渡されます。

配列の内容を変更しました。
メソッド内に新しい配列を作成する必要があります。そのコピーでは、行を削除できます。
次に、そのコピーを返します。

于 2013-02-07T01:43:02.847 に答える
1

他の人が指摘したように、配列はオブジェクトであり、次のとおりです。

Java はオブジェクトを値渡しの参照として渡します

引用:Javaは「参照渡し」または「値渡し」ですか?

つまり、メソッドRemovedLinesに入る_baseImageと、同じオブジェクトをimageArray指す参照になります (ヒープ内の同じオブジェクトを指す 2 つの異なる参照)。

したがって、最初のステップは、元の配列のコピーを作成することです。方法は次のとおりです。

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 に答える