Java:どのようにパスbyte[]による。
-
22-07-2019 - |
質問
の取得ができないことがあります。当期純に"をキーワードに関係していることから、こうした.はありませんがJava?
解決
メソッドで何をしていますか?既存の配列にデータを追加するだけの場合、参照渡しのセマンティクスは必要ありません(.NETまたはJavaのいずれか)。どちらの場合も、参照は値で渡されるため、オブジェクトへの変更は呼び出し元に表示されます。それはあなたの家の住所を誰かに伝え、何かを届けるように頼むようなものです。問題ありません。
参照渡しのセマンティクスを本当にしたい場合、つまり、呼び出し元はパラメーター自体に加えられた変更を見ることができます。 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はパススルーによる価値Dammit!
こちらは、コンクリートの例:
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
方法と送信 aコピーを参考に new byte[8]
を使用 パススルーによる価値.その後、 modifyArray
方法 捨てたのコピー基準により作成 new byte[16]
.にします。 modifyArray
, への参 new byte[16]
の範囲(最終的にゴミを収集します。) しかし、 main
方法も参考に new byte[8]
できるというだけのことだ 送信コピーした参考 ではなく、実際の参照の参考文献をご参照ください。
れることを明確に示すべきであるJavaのメソッドは参考用のパススルーによる値。
Javaはメソッド引数に値渡しを使用します。
- プリミティブ(int、booleanなど。)Javaの特殊なケースです。オブジェクト自体ではありません。この場合、プリミティブ(引数)のコピーが関数に渡されます。これは、パスバイバリュー理論とうまく調和しています。
- オブジェクトの場合、オブジェクトへの参照は値で渡されます(オブジェクトではなく参照のコピーが作成されます)...両方の参照が同じオブジェクトを指します。したがって、メソッドのオブジェクトパラメータを変更すると、実際のオブジェクトが変更されます。
この記事はあなたを助けるはずです。 http://www.javaworld.com/ javaworld / javaqa / 2000-05 / 03-qa-0526-pass.html
OPの質問に関しては、byte []配列への参照をメソッドに渡すだけです。最終結果は、参照渡しに似ています。バイト配列を変更すると、呼び出し元はメソッド実行後の変更を確認できます。
抵抗を鎮めるための更新:) =&gt;出力を示します
.NET Land
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
}
Java Land
マイナー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
}