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

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

10 ответов

Решение

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

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

  • массив
  • Коллекция
  • класс 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,

Как сделать звонок по ссылке в 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, как мы делаем в C и C++??

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

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

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

Collections.sort(list, new Comparator() {

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

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

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

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

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

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

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

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

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

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

int[] byRef = new int[1];
byRef[0] = 1;
foo(byRef);
// ==> byRef[0] == 2.

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

Я использовал для этого массив...

    package method;


    import java.util.Scanner;

    public class InterChange {



        public static void main(String[] args) {

        Scanner sc=new Scanner(System.in);

        int a[]=new int[2];

        System.out.println("Enter two values");

        for(int i=0;i<2;i++) {

            a[i]=sc.nextInt();
        }




        hange(a);

        for(int i=0;i<2;i++) {

            System.out.println(a[i]);
        }


    }




     static int hange(int b[])
    {
        int temp;

        temp=b[0];
        b[0]=b[1];
        b[1]=temp;
        return b[0]&b[1];

    }

    }

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

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

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

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

ОП: 9 3 2 2

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

Да, вы можете реализовать вызов по ссылке другим способом, используя функцию " Передача по ссылке ".

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

В приведенном ниже коде исходные данные → x обрабатываются путем передачи ссылочного объекта.

public class Method_Call {
static int x=50;
public void change(Method_Call obj) {
    obj.x = 100;
}

public static void main(String[] args) {

    Method_Call obj = new Method_Call();
    System.out.println(x);
    obj.change(obj);
    System.out.println(x);

}

}

Выход: 50 100

Другие вопросы по тегам