Java против C ++ передать по ссылке - PullRequest
6 голосов
/ 06 октября 2010


Я запутался в следующем:
В C ++ мы можем передать параметр в функцию по ссылке (объявив его как указатель или ссылочную переменную), и если мы изменим его внутри функции, изменения будут отражены вызывающей стороне, когда функция вернется. Это не происходит в Java, и я не уверен, что понимаю, почему.

например. это метод из объекта X

public boolean aMethod(int id, myClass aClass)
{
   //do some logic
   aClass = new MyClass();
   //configure argument object aClass
   return true;
}

В телефонный код :

//some code processing
myClass obj = null;
if(X.aMethod(2,obj))
{
  obj.methodA();//start using the object
}

Я использую его в C ++, то есть для возврата результата, который сообщает, что можно использовать параметр функции, но в Java это не работает.
Я вхожу в ветку if (X.aMethod (2, obj)), но объект равен null. Почему это ноль?
Разве я не назначил адрес памяти из кучи, используя new внутри метода aMethod (int id, myClass aClass)? Я не передаю "адрес" объекта в функции? Я ожидал, что объект obj будет правильно сконструирован и использован в вызывающем коде. Я неправильно понял что-то, касающееся памяти в Java?

Ответы [ 6 ]

27 голосов
/ 06 октября 2010

Java передает все по значению - , включая ссылки .

. Это означает, что если вы передаете объект, вы можете изменить свойства этого объекта иони сохранятся после вашего возвращения, но вы не можете заменить объект целиком на совершенно новый объект, потому что вы не можете изменить ссылку - только то, что ссылкауказывает на.

Перед вашей aClass = строкой:

Outside the function:

    obj ---> <foo>

Inside the function:

    aClass ---> <foo>

После вашей aClass = строки:

Inside the function:

    aClass ---> <bar>

Outside the function:

    obj ---> <foo>

Ключевым моментом, на который следует обратить внимание, является то, что aClass не указывает на obj - оно указывает на <foo>.Вы не передаете адрес obj, вы передаете адрес того, что obj указывает на .Таким образом, когда вы изменяете то, на что указывает aClass, это не касается obj.


В качестве альтернативного способа мышления:

В Java

Bar foo = new Bar();

эквивалентно C ++,

Bar *foo = new Bar();

Таким образом, когда вы передаете foo функции, вы не передаете адрес foo - вы передаете адресвыделенного объекта.В Java нет передачи по ссылке в стиле &, как в C / C ++.

4 голосов
/ 08 октября 2010

Прочтите мою статью на эту тему "Java - это ценность, черт побери"

http://javadude.com/articles/passbyvalue.htm

3 голосов
/ 06 октября 2010

В C ++, что бы произошло, если бы вы сделали это:

 void myFunct( int * pInt) {
     pInt = // something;
 }

 // caller
 int x;
 int * myPointer = & x;
 myFunc(myPointer);
 // where does myPointer point now? 

присваивание внутри myFunc не влияет на указатель вызывающего.Теперь, если myFunct вместо этого использует указатель на указатель

 void myFunct( int ** ppInt) {
     *ppInt = // something;
 }

или ссылку на указатель, то вы увидите изменение в вызывающей стороне, и это, как я полагаю, вы делаете.

В Java

 void myFunct (Integere anInteger) {
       // anInteger is  reference to whatever is passed
       anInteger = new Integer(99); // no effect on caller
 }

мы действительно передаем ссылки на функцию, вышеприведенный anInteger - это ссылка на объект, принадлежащий вызывающей стороне, но anInteger - значение, локальное для метода, присваивающего ему, аналогично присвоениюpint в первом примере, не влияет на вызывающего.

2 голосов
/ 06 октября 2010

Комментарий в вашем примере предполагает, что существует метод aMethod для настройки объекта. Таким образом, вместо того, чтобы передавать значение null, как насчет создания экземпляра объекта, а затем его передачи. В качестве альтернативы, вы можете заставить метод возвращать объект intead, например, так:

public boolean aMethod(int id)
{
  myClass aClass = new MyClass();
  return myclass;
}

И

myClass obj = X.aMethod(2);
if(obj != null)
{
  obj.methodA();//start using the object
}

В качестве альтернативы я предпочитаю договориться, что aMethod всегда должен возвращать действительный объект. Если это невозможно, например, из-за ошибки в конфигурации, заставьте метод вызвать исключение.

1 голос
/ 06 октября 2010

Java не может сделать «передать по ссылке».

Java использует " передача по значению ".

0 голосов
/ 06 октября 2010

рассмотрите аргументы вашего объекта (в Java), переданные как таковые (проиллюстрировано в C ++):

void method(TObject* arg);
...