.NETでは、キーワード "ref"を使用してそれを行うことができます。 Javaでそうする方法はありますか?
あなたの方法で何をしていますか?既存の配列にデータを入力するだけの場合は、.NETでもJavaでも、参照渡しのセマンティクスは必要ありません。どちらの場合も、参照は値で渡されます。したがって、objectへの変更は、呼び出し元に表示されます。それは誰かにあなたの家の住所を伝え、それに何かを届けるように頼むようなものです-問題ありません。
あなたが本当に参照渡しのセマンティクスが必要な場合、つまり、呼び出し元はパラメータ自体に加えられた変更をすべて見ることができます。 nullまたは別のバイト配列への参照に設定する場合、いずれかのメソッドが新しい値を返すか、またはバイト配列への参照を含み、 (変更された可能性がある)参照は後で参照から取得されます。
つまり、メソッドが次のようになっている場合:
public void doSomething(byte[] data)
{
for (int i=0; i < data.length; i++)
{
data[i] = (byte) i;
}
}
その後、あなたは大丈夫です。メソッドが次のようになっている場合:
public void createArray(byte[] data, int length)
{
// Eek! Change to parameter won't get seen by caller
data = new byte[length];
for (int i=0; i < data.length; i++)
{
data[i] = (byte) i;
}
}
次に、次のいずれかに変更する必要があります。
public byte[] createArray(int length)
{
byte[] data = new byte[length];
for (int i=0; i < data.length; i++)
{
data[i] = (byte) i;
}
return data;
}
または:
public class Holder<T>
{
public T value; // Use a property in real code!
}
public void createArray(Holder<byte[]> holder, int length)
{
holder.value = new byte[length];
for (int i=0; i < length; i++)
{
holder.value[i] = (byte) i;
}
}
詳細については、 C#で渡されるパラメーター および Javaで渡されるパラメーター を参照してください。 (前者の方が後者よりも優れていると思います。恐れます。いつかアップデートに取り掛かります。)
実際、Javaでは、参照は値で渡されますです。
この場合、参照は_byte[]
_オブジェクトです。オブジェクト自体に影響する変更は、呼び出し元のメソッドから確認されます。
ただし、たとえば_new byte[length]
_を使用して参照を置き換えようとすると、値渡しによって取得された参照のみが置き換えられるため、呼び出し元メソッドの参照は変更されません。
この問題についての興味深い記事は次のとおりです。 Javaは値渡しのダンミです
具体的な例を次に示します。
_public class PassByValue
{
public static void modifyArray(byte[] array)
{
System.out.println("Method Entry: Length: " + array.length);
array = new byte[16];
System.out.println("Method Exit: Length: " + array.length);
}
public static void main(String[] args)
{
byte[] array = new byte[8];
System.out.println("Before Method: Length: " + array.length);
modifyArray(array);
System.out.println("After Method: Length: " + array.length);
}
}
_
このプログラムは、byte
メソッドで長さ_8
_のmain
配列を作成します。これにより、modifyArray
メソッドが呼び出され、新しいbyte
長さ_16
_の配列が作成されます。
byte
メソッドで新しいmodifyArray
配列を作成することにより、byte
メソッドに戻ったときのmain
配列の長さは_16
_になるように見えるかもしれませんが、このプログラムを実行すると別の何かが明らかになります:
_Before Method: Length: 8
Method Entry: Length: 8
Method Exit: Length: 16
After Method: Length: 8
_
byte
メソッドから戻る際のmodifyArray
配列の長さは、_8
_ではなく_16
_に戻ります。
何故ですか?
これは、main
メソッドがmodifyArray
メソッドを呼び出して_new byte[8]
_へのコピーされた参照をpass-by-valueを使用して送信したためです。次に、modifyArray
メソッド_new byte[16]
_を作成して、コピーされた参照を破棄しました。 modifyArray
を終了するときまでに、_new byte[16]
_への参照は範囲外です(最終的にはガベージコレクションされます。)ただし、main
メソッドは、_new byte[8]
_への参照をまだ持っていますコピーされた参照を送信であり、参照への実際の参照ではありません。
これは、Javaが値渡しを使用して参照を渡すことを示しています。
Javaはメソッド引数に値渡しを使用します。
この記事はあなたに役立つはずです。 http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
OPの質問については、byte []配列への参照をメソッドに渡すだけです。最終結果は、参照渡しと同様になります。バイト配列を変更すると、呼び出し元はメソッド実行後の変更を確認できます。
抵抗を抑えるための更新:)=>出力を示します
class Counter
{
private int m_count = 0;
public override string ToString()
{
return String.Format("Counter ID{0} : Value {1}", this.GetHashCode(), m_count);
}
public void Increment()
{ m_count++; }
}
class MakeAPass
{
public void PassByValueAndModify(int i)
{ i = 20; }
public void PassByRefAndModify(ref int i)
{ i = 20; }
public void PassByValueAndModify(Counter c)
{ c.Increment(); }
public void PassByRefAndModify(ref Counter c)
{ c.Increment(); }
public void PassByRefAndReassign(ref Counter c)
{
c = new Counter();
for (int i=0; i<5; ++i)
c.Increment();
}
}
static void Main(string[] args)
{
MakeAPass obj = new MakeAPass();
int intVal = 10;
obj.PassByValueAndModify(intVal);
Console.WriteLine(intVal); // => 10
obj.PassByRefAndModify(ref intVal);
Console.WriteLine(intVal); // => 20
Counter obCounter = new Counter();
obj.PassByValueAndModify(obCounter);
Console.WriteLine(obCounter.ToString()); // => Counter ID58225482 : Value 1
obj.PassByRefAndModify(ref obCounter);
Console.WriteLine(obCounter.ToString()); // => Counter ID58225482 : Value 2
obj.PassByRefAndReassign(ref obCounter);
Console.WriteLine(obCounter.ToString()); // => Counter ID54267293 : Value 5
}
マイナーmods reqd:hashCode()と+を使用してCounter.Javaで文字列を連結します...
class MakeAPass
{
public void PassByValueAndModify(int i)
{ i = 20; }
// can't be done.. Use Integer class which wraps primitive
//public void PassByRefAndModify(ref int i)
public void PassByValueAndModify(Counter c)
{ c.Increment(); }
// same as above. no ref keyword though
//public void PassByRefAndModify(ref Counter c)
// this can't be done as in .net
//public void PassByRefAndReassign(ref Counter c)
public void PassAndReassign(Counter c)
{
c = new Counter();
for (int i=0; i<5; ++i)
c.Increment();
}
}
public static void main(String args[])
{
MakeAPass obj = new MakeAPass();
int intVal = 10;
obj.PassByValueAndModify(intVal);
System.out.println(intVal); // => 10
//obj.PassByRefAndModify(ref intVal);
//System.out.println(intVal); // can't get it to say 20
Counter obCounter = new Counter();
obj.PassByValueAndModify(obCounter);
System.out.println(obCounter.ToString()); // => Counter ID3541984 : Value 1
//obj.PassByRefAndModify(ref obCounter);
//Console.WriteLine(obCounter.ToString()); // no ref. but can make it 2 by repeating prev call
obj.PassAndReassign(obCounter);
System.out.println(obCounter.ToString()); // => Counter ID3541984 : Value 1
// can't get it to say 5
}