Как сделать звонок по ссылке в Java? - PullRequest
26 голосов
/ 17 мая 2011

Поскольку Java не поддерживает указатели, как можно вызвать функцию по ссылке в Java, как мы делаем это в C и C ++ ??

Ответы [ 10 ]

37 голосов
/ 17 мая 2011

Реальная передача по ссылке невозможна в Java.Java передает все по значению, включая ссылки.Но вы можете смоделировать это с контейнером объектов.

Используйте любой из них в качестве параметра метода:

  • массив
  • a Collection
  • класс AtomicXYZ

И если вы измените его содержимое в методе, измененное содержимое будет доступно вызывающему контексту.


Упс, вы, очевидно, имеете в виду вызов метода по ссылке.Это также невозможно в Java, так как методы не являются гражданами первого уровня в Java. Это может измениться в JDK 8 , но на данный момент вам придется использовать интерфейсы для обхода этого ограничения.

public interface Foo{
    void doSomeThing();
}

public class SomeFoo implements Foo{
    public void doSomeThing(){
       System.out.println("foo");
    }
}

public class OtherFoo implements Foo{
    public void doSomeThing(){
       System.out.println("bar");
    }
}

Используйте Foo в своем коде, чтобы выможет легко заменить SomeFoo на OtherFoo.

10 голосов
/ 17 мая 2011

Как сделать вызов по ссылке в Java?

Вы не можете сделать вызов по ссылке в Java.Период.Ничто даже близко не подходит.И передача ссылки по значению НЕ совпадает с вызовом по ссылке.

(Реальный «вызов по ссылке» позволяет вам делать такие вещи:

void swap(ref int i, ref int j) { int tmp = *i; *i = *j; *j = tmp }

int a = 1;
int b = 2;
swap(a, b);

Вы просто можете 'сделать это в Java.)


Поскольку Java не поддерживает указатели ...

Хотя это технически верно, это не будет препятствием для того, чтоты пытаешься сделать.

Java поддерживает поддержку ссылок , которые в большинстве важных моментов похожи на указатели.Разница в том, что вы не можете рассматривать ссылки как адреса памяти, выполняя арифметику с ними, преобразовывая их в целочисленные типы и из них и так далее.И вы не можете создать ссылку на переменную, потому что концепция не существует в Java или архитектуре JVM.


Как можно вызывать функцию по ссылке в Java, как мыdo в C и C ++ ??

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

Однако вы можете определить класс с помощью одного метода экземпляра и использовать экземпляр класса вместо ссылки на функцию.Другие ответы приводят примеры такого подхода.

2 голосов
/ 17 мая 2011

Обычно в Java это решается с помощью интерфейсов:

Collections.sort(list, new Comparator() {

  @Override
  public int compareTo(Object o1, Object o2) {
  /// code
  }

});
1 голос
/ 11 сентября 2013
package jgf;

public class TestJavaParams {

 public static void main(String[] args) {
    int[] counter1 = new int[1];
    counter1[0] = 0;
    System.out.println(counter1[0]);
    doAdd1(counter1);
    System.out.println(counter1[0]);
    int counter2 = 0;
    System.out.println(counter2);
    doAdd2(counter2);
    System.out.println(counter2);   
  }

  public static void doAdd1(int[] counter1) {
    counter1[0] += 1;
  }

  public static void doAdd2(int counter2) {
    counter2 += 1;
  }
}

Вывод будет:

0
1
0
0
1 голос
/ 17 мая 2011

В Java, за исключением примитивов, передача Object в метод / функцию всегда осуществляется по ссылке.См. ответ Оли Чарлворта для примера.

Для примитивных типов вы можете обернуть его, используя массив: Например:

public void foo(int[] in){
  in[0] = 2;
}

int[] byRef = new int[1];
byRef[0] = 1;
foo(byRef);
// ==> byRef[0] == 2.
1 голос
/ 17 мая 2011

Лучший способ - использовать интерфейс, который выполняет действие.

// Pass a Runnable which calls the task() method
executor.submit(new Runnable() {
    public void run() {
        task();
    }
});

public void task() { }

Вы можете использовать отражения для вызова любого метода

Method method = MyClass.class.getMethod("methodToCall", ParameterType.class);
result = method.invoke(object, args);
0 голосов
/ 16 декабря 2016

JAVA разрешает внутреннюю ссылку с использованием объектов. Когда один написать это назначение Obj o1 = новый Obj (); Obj o2 = o1; Что он делает, что и o1 и o2 указывают на один и тот же адрес. Манипулируя пространством любого объекта, отразится и на другом.

Таким образом, как указано выше, вы можете использовать Array, Collections

0 голосов
/ 20 августа 2014

Из Java. Полный справочник Герберта Шильдта, 9-е издание: «Когда вы передаете объект методу, ситуация резко меняется, потому что объекты передаются с помощью того, что фактически вызывается по ссылке. Имейте в виду, что при созданиипеременная типа класса, вы только создаете ссылку на объект. Таким образом, когда вы передаете эту ссылку методу, получающий ее параметр будет ссылаться на тот же объект, на который ссылается аргумент. Это фактически означает, чтообъекты действуют так, как если бы они были переданы в методы с помощью метода call-by-reference. Изменения объекта внутри метода влияют на объект, используемый в качестве аргумента. "

package objectpassing;

public class PassObjectTest {

    public static void main(String[] args) {
        Obj1 o1 = new Obj1(9);
        System.out.println(o1.getA());
        o1.setA(3);
        System.out.println(o1.getA());
        System.out.println(sendObj1(o1).getA());
        System.out.println(o1.getA());
    }

public static Obj1 sendObj1(Obj1 o)
{
    o.setA(2);
    return o;
}


}

class Obj1
{
    private int a;

    Obj1(int num)
    {
        a=num;
    }

    void setA(int setnum)
    {
        a=setnum;
    }

    int getA()
    {
        return a;
    }
}

OP: 9 3 22

Финальный вызов getA () показывает, что поле исходного объекта 'a' было изменено при вызове метода public static Obj1 sendObj1 (Obj1 o).

0 голосов
/ 22 марта 2014

Java разрешает только вызов по значению.Однако ссылки на объекты могут быть переданы в вызываемую функцию с помощью вызова по значению.Эти ссылки, если они используются для манипулирования данными объекта в вызываемой функции, это изменение также будет видно в вызывающей функции.Мы не можем делать арифметику указателей для ссылок, как мы делаем с указателями, но ссылки могут указывать на данные объекта, используя оператор периода, который функционирует как оператор '*' в C / C ++.

0 голосов
/ 10 сентября 2012

http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html

Java манипулирует объектами по ссылке, а все переменные объекта являются ссылками. Однако Java не передает аргументы метода по ссылке; он передает их по значению.

...