web-dev-qa-db-ja.com

参照によりプリミティブデータ型を渡すにはどうすればよいですか?

Javaで参照によってプリミティブ型を渡すにはどうすればよいですか?たとえば、メソッドに渡すintを変更可能にするにはどうすればよいですか?

43
Neuquino

Javaで参照によってプリミティブを直接渡す方法はありません。

回避策は、代わりにラッパークラスのインスタンスへの参照を渡すことです。このクラスには、プリミティブがメンバーフィールドとして含まれます。このようなラッパークラスは、ご自身で簡単に記述できます。

public class IntRef { public int value; }

しかし、事前に作成されたラッパークラスについてはどうでしょうか。独自のラッパークラスを作成する必要はありません。 OK:

Apache commons-lang Mutable *クラス:
利点:シングルスレッドでの使用に適したパフォーマンス。完全。
短所:サードパーティのライブラリ依存関係を導入します。組み込みの同時実行制御はありません。
代表クラスMutableBooleanMutableByteMutableDoubleMutableFloatMutableIntMutableLongMutableObjectMutableShort .

Java.util.concurrent.atomic Atomic *クラス:
Advantages:標準のJava(1.5+)API。組み込みの同時実行制御。
短所:シングルスレッド設定で使用すると、パフォーマンスがわずかに低下します。一部のデータ型の直接サポートがありません。 AtomicShortはありません。
代表クラスAtomicBooleanAtomicIntegerAtomicLong 、および- AtomicReference
:ユーザーColinD 回答で表示 の場合、AtomicReferenceを使用して、欠落しているクラスの一部を近似できます。アトミックショート。

長さ1のプリミティブ配列
OscarRyzの答え は、長さ1の配列を使用してプリミティブ値を「ラップ」する方法を示しています。
利点:簡単に記述できます。パフォーマー。サードパーティのライブラリは必要ありません。
欠点:少し汚い。組み込みの同時実行制御はありません。 (明らかに)自己文書化しないコードの結果:メソッドシグネチャの配列はそこにあるので、複数の値を渡すことができますか?または、参照渡しエミュレーションの足場としてここにありますか?

も参照してください
StackOverflowの質問への回答 " Javaの可変ブールフィールド "。

私の意見
Javaでは、上記のアプローチを控えめに使用するか、まったく使用しないようにしてください。 Cでは、関数の戻り値を使用してステータスコード(SUCCESS/FAILURE)を中継するのが一般的ですが、関数の実際の出力は1つ以上の出力パラメーターを介して中継されます。 Javaでは、リターンコードの代わりに例外を使用するのが最適です。これにより、メソッドの戻り値が解放され、実際のメソッド出力を運ぶために使用されます。ほとんどのJavaプログラマーは、アウトパラメーターよりも自然であることがわかります。

73
Mike Clark

Javaの何も参照渡しされません。すべて値渡しされます。

編集:プリミティブとオブジェクトタイプの両方が値で渡されます。渡された値/参照を変更したり、元の値/参照が変更されることを期待したりすることはできません。例:

String a;
int b;

doSomething(a, b);

...

public void doSomething(String myA, int myB) {
   // whatever I do to "myA" and "myB" here will never ever ever change
   // the "a" and "b"
}

このハードルを回避する唯一の方法は、プリミティブまたは参照に関係なく、コンテナオブジェクトを渡すか、戻り値を使用することです。

ホルダー付き:

private class MyStringHolder {
  String a;
  MyStringHolder(String a) {
    this.a = a;
  }
}

MyStringHolder holdA = new MyStringHolder("something");

public void doSomething(MyStringHolder holder) {
   // alter holder.a here and it changes.
}

戻り値あり

int b = 42;
b = doSomething(b);

public int doSomething(int b) {
  return b + 1;
}
13
Martin Algesten

代わりにAtomicIntegerAtomicBooleanなどを渡します。すべてのプリミティブ型に対応するわけではありませんが、たとえば、AtomicReference<Short>必要に応じて。

注:Javaでこのようなことをする必要はほとんどありません。あなたがそれをしたいときは、あなたがしようとしていることを再考し、他の方法でそれを行うことができないかどうかを確認することをお勧めします(intを返すメソッドを使用して、たとえば...最善の方法は状況によって異なります)。

13
ColinD

これはJavaでは不可能です。代わりに、単一の要素配列にラップすることができます。

void demo() { 
    int [] a = { 0 };
    increment ( a ) 
}
void increment( int [] v ) { 
     v[0]++;
}

しかし、常により良いオプションがあります。

10
OscarRyz

できません。しかし、変更された値である整数を返すことができます

int i = 0;
i = doSomething(i);

複数を渡す場合は、 データ転送オブジェクト (クラスに渡すことができる変数のセットを含むクラス)を作成することができます。

3

その値を持つオブジェクトをフィールドとして渡します。

2
Dan D.

Javaでは不可能です