web-dev-qa-db-fra.com

Comment faire appel par référence en Java?

Comme Java ne supporte pas les pointeurs, comment est-il possible d'appeler une fonction par référence en Java comme nous le faisons en C et C++?

26
Shashi Bhushan

Le passage par référence est impossible en Java. Java passe tout par valeur, y compris les références. Mais vous pouvez le simuler avec des objets conteneurs. 

Utilisez l'un de ceux-ci comme paramètre de méthode:

  • un tableau
  • une collection
  • une classe AtomicXYZ

Et si vous modifiez son contenu dans une méthode, le contenu modifié sera disponible pour le contexte appelant.


Oups, vous voulez apparemment dire appeler une méthode par référence. Cela n’est pas non plus possible en Java, car les méthodes ne sont pas des citoyens de premier niveau en Java. Cela peut changer dans JDK 8 , mais pour le moment, vous devrez utiliser des interfaces pour contourner cette limitation.

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

Utilisez Foo dans votre code pour pouvoir facilement remplacer SomeFoo par OtherFoo.

37

Comment faire appel par référence en Java?

Vous ne pouvez pas appeler par référence en Java. Période. Rien ne vient même près. Et passer une référence par valeur n'est PAS la même chose qu'un appel par référence.

(Le vrai "appel par référence" vous permet de faire ce genre de chose:

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

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

Vous ne pouvez simplement pas le faire en Java.)


Puisque Java ne supporte pas les pointeurs ...

Bien que cela soit techniquement vrai, cela ne constituerait pas un obstacle à ce que vous essayez de faire. 

Java fait support references, qui sont comme des pointeurs dans les aspects les plus importants. La différence est que vous ne pouvez pas traiter les références comme des adresses mémoire en effectuant des opérations arithmétiques, en les convertissant en types entiers, etc. Et vous ne pouvez pas créer de référence à une variable car le concept n'existe pas dans Java ni dans l'architecture JVM.


Comment est-il possible d'appeler une fonction par référence en Java comme nous le faisons en C et C++?

En Java, les fonctions (méthodes) et les références aux fonctions ne sont pas prises en charge en tant que valeurs. Donc, vous ne pouvez pas les passer comme arguments et vous ne pouvez pas les affecter à des variables. 

Cependant, vous can définissez une classe avec une méthode d'instance et utilisez une instance de la classe au lieu d'une référence de fonction. Autres réponses donne des exemples de cette approche.

10
Stephen C

Généralement, en Java, cela est résolu en utilisant des interfaces:

Collections.sort(list, new Comparator() {

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

});
2
Vladimir Ivanov

Le meilleur moyen consiste à utiliser une interface qui effectue l'action.

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

public void task() { }

Vous pouvez utiliser des réflexions pour appeler n'importe quelle méthode.

Method method = MyClass.class.getMethod("methodToCall", ParameterType.class);
result = method.invoke(object, args);
1
Peter Lawrey

En Java, à l'exception des primitives, le passage d'Object à une méthode/fonction est toujours par référence . Voir l'exemple de la réponse de Oli Charlesworth .

Pour les types primitifs, vous pouvez l'envelopper à l'aide de array: Par exemple:

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

int[] byRef = new int[1];
byRef[0] = 1;
foo(byRef);
// ==> byRef[0] == 2.
1
Trung
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;
  }
}

La sortie serait:

0
1
0
0
1
JGFMK

Java autorise la référence interne en utilisant des objets. Lorsque vous écrivez cette affectation. la même adresse . Manipuler l'espace de n'importe quel objet, reflétera également dans l'autre.

Donc, pour ce faire, comme mentionné ci-dessus, vous pouvez utiliser Array, Collections

0
Yash Bansal

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

Java manipule les objets par référence et toutes les variables d'objet sont des références. Cependant, Java ne transmet pas les arguments de méthode par référence; il les passe par valeur.

0
Swetha D Murthy

From Java The Complete Reference de Herbert Shildt 9ème édition: "Lorsque vous transmettez un objet à une méthode, la situation change radicalement, car les objets sont passés par ce qui est effectivement appelé par référence. N'oubliez pas que lorsque vous créez une variable de En tant que type de classe, vous ne faites que créer une référence à un objet. Ainsi, lorsque vous transmettez cette référence à une méthode, le paramètre qui le reçoit fait référence au même objet que celui référencé par l'argument. Cela signifie en fait que les objets agissent comme s'ils sont transmis aux méthodes à l'aide de call-by-referen ce. Les modifications apportées à l'objet dans la méthode affectent l'objet utilisé en tant qu'argument. "

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 2 2

L'appel final à getA () affiche le champ d'objet d'origine 'a' a été modifié dans l'appel à la méthode public static Obj1 sendObj1 (Obj1 o). 

0
Dave Black

Java permet uniquement d'appeler par valeur. Cependant, les références aux objets peuvent être transférées à la fonction appelée à l'aide de l'appel par la valeur. Si ces références sont utilisées pour manipuler les données de l'objet dans la fonction appelée, cette modification sera également visible dans la fonction appelante. Nous ne pouvons pas faire d'arithmétique de pointeur sur les références comme nous le faisons avec des pointeurs, mais les références peuvent pointer sur les données de l'objet à l'aide de l'opérateur de période qui fonctionne comme opérateur '*' en C/C++. 

0
user3449128