Вопрос

Вы можете сделать это в .NET, используя ключевое слово «ref».Есть ли способ сделать это на 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 - это чёртова передача по значению! <Ч>

Вот конкретный пример:

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);
    }
}

Эта программа создаст массив байтов длиной 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 и отправил скопированную ссылку на новый код [8] с помощью передачи по значению . Затем метод modifyArray отбросил скопированную ссылку, создав новый байт [16] . К тому времени, когда мы покидаем modifyArray , ссылка на новый байт [16] выходит из области видимости (и в конечном итоге будет собирать мусор). Однако главная часть Метод по-прежнему имеет ссылку на новый байт [8] , так как он только отправляет скопированную ссылку , а не фактическую ссылку на ссылку.

Это должно продемонстрировать, что Java будет передавать ссылку, используя передачу по значению.

Java использует передачу по значению для аргументов метода.

  • Примитивы (int, boolean и т. д.) являются особыми случаями в Java.не объекты как таковые.В этом случае в функцию передается копия примитива (аргумента).Это хорошо сочетается с теорией передачи ценностей.
  • Для объектов происходит следующее: ссылка на объект передается по значению (создается копия ссылки, а не объекта)...но обе ссылки указывают на один и тот же объект.Поэтому, если вы измените параметр объекта в методе, фактический объект будет изменен.

Эта статья должна вам помочь..http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

Что касается вопроса ОП, просто передайте ссылку на массив byte[] в метод.Конечный результат будет аналогичен передаче по ссылке.Если вы измените массив байтов, вызывающая сторона сможет увидеть выполнение изменений после метода.

Обновление, чтобы подавить сопротивление :) => указывает вывод

.NET Земля

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
}

Яванская земля

Требуются незначительные моды:Используйте 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  
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top