8

この問題は何度も対処されていることは知っていますが、私の Java/C++ の知識は非常に弱く、答えをほとんど理解できません :-( ... 私が本当に望んでいるのは、非常に単純な例です。

C++ では、次のように記述できます。

void func()
{
  int x = 3;
  add_one(x);
  // now x is 4.
}
void add_one(int &var)
{
  var++;
}

私が今見たいのは、Java で同じ効果を達成する最も簡単な方法です。

4

6 に答える 6

10

直接できません。あなたが得ることができる最も近い方法は、値をオブジェクトに入れ、参照を(値によって、参照がコピーされるように)メソッドに渡すことです。

void func()
{
  int x = 3;
  int[] holder = [x];
  add_one(holder);
  // now holder[0] is 4.  x is still 3.
}

// container here is a copy of the reference holder in the calling scope.
// both container and holder point to the same underlying array object
void add_one(int[] container)
{
    container[0]++;
}

ここでは配列を使用していますが、ラッパーは任意のオブジェクトにすることができます。

于 2012-07-11T16:42:06.857 に答える
3

Java メソッドの引数は値渡しであり、関数内で変更することはできません。オブジェクトまたは配列で int (またはその他のプリミティブ型) をラップする必要があります。オブジェクトまたは配列をメソッド引数として渡すと、オブジェクトの変更に使用できる参照が渡されます。

Java には、プリミティブ型 ( Integerなど) 用の Object ベースのラッパーが既にありますが、これらは設計上不変です。一部のライブラリは、これらのラッパーの変更可能なバージョンを提供します。独自のものを作成することもできます:

public class MutableInt
{
    private int val;

    public MutableInt(int val)
    {
        this.val = val;
    }

    public void setValue(int newVal)
    {
        this.val = newVal;
    }

    public int getValue()
    {
        return this.val;
    }
}

void func()
{
    int x = 3;
    MutableInt wrapper = new MutableInt(x);
    add_one(wrapper);
}

void add_one(MutableInt arg)
{
    arg.setValue(arg.getValue() + 1);
}
于 2012-07-11T16:49:16.067 に答える
2

これはできません。Javaは値渡しのみです。プリミティブは明らかですが、オブジェクトに渡されるのは参照であり、オブジェクト自体ではありません。

于 2012-07-11T16:42:15.683 に答える
0

他の回答からわかるように、Javaは純粋に値渡しです。オブジェクトは、「値参照」と呼ばれるものによって渡されます。Javaのオブジェクトは単なるポインタ参照であるため、「値」はオブジェクトがヒープ上に存在するアドレスと考えることができます。したがって、メソッド呼び出しを行うときは、「値」、別名アドレスをメソッドパラメーターにコピーします。

Object x = new Object();
foo(x);

オブジェクト作成中

ヒープ->オブジェクトの割り当て(5000)

変数宣言

スタック->ローカル変数の割り当て(1000)

変数の割り当て

スタックアドレス1000を5000に設定(オブジェクトインスタンスを指すため)

したがって、ここには2つの別々のメモリ割り当てがあることがわかります。変数の「値」は、ヒープ上のアドレスと見なされます。

メソッド呼び出し

スタック->メソッドパラメータ8000の割り当て

スタックアドレス8000は、渡されたパラメータ5000と同じ値に設定されます

これが、メソッドでオブジェクトインスタンスを再割り当てした場合、それが呼び出し元に伝播されない理由です。スタック位置8000のヒープ位置を変更したはずです。また、呼び出し元のメソッドのスタック位置1000の値は5000(元のオブジェクトインスタンス)のままです。

Cでは次のように考えてください。

void method(myobject * obj);

あなたは確かに"obj"のフィールドを変更することができます、そしてあなたはこれをローカルで行うことができます:

obj = new myobject();

ただし、呼び出し元には、渡された元の値が引き続き表示されます。

Javaには、&reference演算子に類似したものはありません。

そして、あなたの目的のために使用できる組み込みのクラスがあります。AtomicInteger、AtomicLongなどは変更可能ですが、同期が関係しているためにパフォーマンスが低下する可能性があります。

参照によるパスをシミュレートするすべての状況を説明するために、汎用のValueHolderクラスをお勧めします。

public class ValueHolder<T> {
    private T value;
    // getter/setter/constructor
}
于 2012-07-11T17:37:53.680 に答える
-3
public int getOneMore(int val) {
  return val + 1;
}
于 2012-07-11T16:44:43.523 に答える
-3

Java では、オブジェクトの参照によるコピーと、プリミティブ型 (int、float など) の vlaue によるコピーが可能です。これはデフォルトであり、変更されることはありません。関数内の int の値を変更する必要がある場合は、たとえばクラス Integer を使用できます

于 2012-07-11T16:51:00.067 に答える