Java : 참조로 바이트를 통과하는 방법?
-
22-07-2019 - |
문제
키워드 "Ref"를 사용하여 .NET에서 수행 할 수 있습니다. Java에서 그렇게 할 방법이 있습니까?
해결책
방법에서 무엇을하고 있습니까? 기존 배열을 채우는 것만으로도 .NET 또는 Java에서는 추천 시맨틱이 필요하지 않습니다. 두 경우 모두 참조는 가치에 따라 전달됩니다. 물체 발신자가 볼 수 있습니다. 그것은 누군가에게 집의 주소를 말하고 그들에게 무언가를 전달하도록 요청하는 것과 같습니다.
만약 너라면 진짜 Pass-by-reference Semantics를 원합니다. 즉, 발신자는 매개 변수 자체에 대한 변경 사항과 예를 들어 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에서 참조는 가치가 전달됩니다.
이 경우 참조는 a입니다 byte[]
물체. 객체 자체에 영향을 미치는 모든 변경 사항은 발신자 메소드에서 볼 수 있습니다.
그러나 참조를 교체하려고하면 예를 들어 new byte[length]
, 귀하는 Pass-By-Value로 얻은 참조 만 교체하므로 발신자 메소드에서 참조를 변경하지 않습니다.
이 문제에 대한 흥미로운 읽기는 다음과 같습니다. 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);
}
}
이 프로그램은 a를 만들 것입니다 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]
사용하여 통과 값. 그런 다음 modifyArray
방법 a new byte[16]
. 우리가 떠날 때까지 modifyArray
,에 대한 참조 new byte[16]
범위를 벗어났습니다 (그리고 결국 쓰레기가 수집 될 것입니다.) 그러나 main
메소드는 여전히에 대한 참조를 가지고 있습니다 new byte[8]
그대로 복사 된 참조를 보냈습니다 참조에 대한 실제 참조가 아닙니다.
Java는 Pass-By-Value를 사용하여 기준을 통과시킬 것임을 입증해야합니다.
Java는 메소드 인수에 대한 값을 사용합니다.
- 기초 요소 (int, boolean 등)은 Java의 특별한 경우입니다. 이 경우 원시 (인수)의 사본이 함수로 전달됩니다. 이 젤은 합격 값 이론과 잘 어울립니다.
- 객체의 경우, 객체에 대한 심판이 값으로 전달된다는 것입니다 (참조 사본은 객체가 아닌 참조 사본이 만들어집니다). 그러나 두 참조는 동일한 객체를 가리 킵니다. 따라서 메소드에서 객체 매개 변수를 수정하면 실제 객체가 수정됩니다.
이 기사는 당신을 도와 줄 것입니다 ..http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
OP의 질문에 관해서는 바이트 [] 배열을 메소드에 참조하십시오. 순 결과는 참조 별 패스와 유사합니다. 바이트 배열을 수정하면 발신자가 메서드 실행 후 변경 사항을 볼 수 있습니다.
저항을 진압하기 위해 업데이트 :) => 출력을 나타냅니다
.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
}
자바 땅
Minor Mods Reqd : hashcode ()를 사용하여 Coun
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
}