136 votes

Est-ce que Java a quelque chose comme les mots-clés ref et out de C#?

Quelque chose comme ce qui suit :

exemple de référence :

void changeString(ref String str) {
    str = "def";
}

void main() {
    String abc = "abc";
    changeString(ref abc);
    System.out.println(abc); //affiche "def"
}

exemple de sortie :

void changeString(out String str) {
    str = "def";
}

void main() {
    String abc;
    changeString(out abc);
    System.out.println(abc); //affiche "def"
}

1 votes

5 votes

IMO tu ne rates pas grand-chose. La seule fois où j'utilise ref ou out en C# est lorsque j'utilise un motif comme TryParse(), où la méthode renvoie un résultat booléen, et le seul moyen d'obtenir une valeur analysée en est par l'utilisation de ref ou out.

4 votes

Devine quoi, c'est exactement ce dont j'ai besoin d'utiliser! ;)

120voto

Mark Byers Points 318575

Non, Java n'a pas quelque chose comme les mots-clés ref et out de C# pour passer par référence.

Vous ne pouvez passer que par valeur en Java. Même les références sont passées par valeur. Consultez la page de Jon Skeet sur le passage des paramètres en Java pour plus de détails.

Pour faire quelque chose de similaire à ref ou out, vous devriez encapsuler vos paramètres à l'intérieur d'un autre objet et passer la référence de cet objet en tant que paramètre.

0 votes

Et il n'y a rien comme dehors?

5 votes

Il faut approfondir cela. Vous ne pouvez passer que des types primitifs (int, short, char, etc.) en tant que valeur. Et non, il n'y a pas d'out.

17 votes

Ce n'est pas 100% vrai, si vous passez un tableau ou une classe, la référence au tableau ou à l'objet est passée en valeur. Vous pouvez modifier les éléments internes du tableau ou de l'objet et cela se reflétera chez l'appelant.

31voto

OscarRyz Points 82553

Réponse directe: Non

Mais vous pouvez simuler la référence avec des wrappers.

Et faire ce qui suit:

void changeString( _ str ) {
    str.s("def");
}

void testRef() {
     _ abc = new _("abc");
     changeString( abc );
     out.println( abc ); // affiche def
}

Out

void setString( _ref ) {
    ref.s( "def" );
}
void testOut() {
    _ abc = _();
    setString( abc );
    out.println(abc); // affiche def
}

Et essentiellement tout autre type tel que:

_ one = new _(1);
addOneTo( one );

out.println( one ); // Peut afficher 2

47 votes

Je n'ai jamais dit, Vous pouvez le faire de cette manière élégante :P

0 votes

Alors pourquoi cela ne fonctionne-t-il pas : private static void ParseLine(String newline, String[] aWrapper, Integer[] bWrapper) { StringTokenizer st = new StringTokenizer(newline); aWrapper[0] = st.nextToken(); bWrapper[0]= new Integer(st.nextToken()); } ParseLine(newline, new String[] {a}, new Integer[] {b});

3 votes

@user311130 Votre code est difficile à lire, mais vous pourriez créer une nouvelle question en disant quelque chose comme : "J'ai trouvé cette réponse mais ce qui suit ne fonctionne pas

9voto

Levent Divilioglu Points 1026

Actuellement, il n'y a ni de mot-clé ref ni de mot-clé out équivalent dans le langage Java à ma connaissance. Cependant, je viens de transformer un code C# en Java qui utilise le paramètre out et je vais vous expliquer ce que j'ai fait. Vous devez encapsuler n'importe quel objet dans une classe wrapper et passer les valeurs encapsulées dans une instance d'objet wrapper comme suit;

Un exemple simple d'utilisation d'un wrapper

Voici la classe wrapper;

public class Wrapper {
    public Object ref1; // utilisez ceci comme ref
    public Object ref2; // utilisez ceci comme out

    public Wrapper(Object ref1) {
        this.ref1 = ref1;
    }
}

Et voici le code de test;

public class Test {

    public static void main(String[] args) {
        String abc = "abc";
        changeString(abc);
        System.out.println("Objet initial: " + abc); // ne va pas afficher "def"

        Wrapper w = new Wrapper(abc);
        changeStringWithWrapper(w);
        System.out.println("Objet mis à jour: " + w.ref1);
        System.out.println("Objet out: " + w.ref2);
    }

    // Cela ne fonctionnera pas
    public static void changeString(String str) {
        str = "def";
    }

    // Cela fonctionnera
    public static void changeStringWithWrapper(Wrapper w) {
        w.ref1 = "def";
        w.ref2 = "Et ceci devrait être utilisé comme out!";
    }

}

Un exemple concret

Une méthode C#.NET utilisant le paramètre out

Voici une méthode C#.NET qui utilise le mot-clé out;

public bool Contains(T value)
{
    BinaryTreeNode parent;
    return FindWithParent(value, out parent) != null;
}

private BinaryTreeNode FindWithParent(T value, out BinaryTreeNode parent)
{
    BinaryTreeNode current = _head;
    parent = null;

    while(current != null)
    {
        int result = current.CompareTo(value);

        if (result > 0)
        {
            parent = current;
            current = current.Left;
        }
        else if (result < 0)
        {
            parent = current;
            current = current.Right;
        }
        else
        {
            break;
        }
    }

    return current;
}

Équivalent en Java du code C# utilisant le paramètre out

Et l'équivalent en Java de cette méthode avec l'aide de la classe wrapper est le suivant;

public boolean contains(T value) {
    BinaryTreeNodeGeneration result = findWithParent(value);

    return (result != null);
}

private BinaryTreeNodeGeneration findWithParent(T value) {
    BinaryTreeNode current = head;
    BinaryTreeNode parent = null;
    BinaryTreeNodeGeneration resultGeneration = new BinaryTreeNodeGeneration();
    resultGeneration.setParentNode(null);

    while(current != null) {
        int result = current.compareTo(value);

        if(result >0) {
            parent = current;
            current = current.left;
        } else if(result < 0) {
            parent = current;
            current = current.right;
        } else {
            break;
        }
    }

    resultGeneration.setChildNode(current);
    resultGeneration.setParentNode(parent);

    return resultGeneration;
}

Classe wrapper

Et la classe wrapper utilisée dans ce code Java est la suivante;

public class BinaryTreeNodeGeneration>  {

    private BinaryTreeNode   parentNode;
    private BinaryTreeNode   childNode;

    public BinaryTreeNodeGeneration() {
        this.parentNode = null;
        this.childNode = null;
    }

    public BinaryTreeNode getParentNode() {
        return parentNode;
    }

    public void setParentNode(BinaryTreeNode parentNode) {
        this.parentNode = parentNode;
    }

    public BinaryTreeNode getChildNode() {
        return childNode;
    }

    public void setChildNode(BinaryTreeNode childNode) {
        this.childNode = childNode;
    }

}

0 votes

Voir les anciennes réponses.

0 votes

Donner une réponse détaillée à un vote négatif est amusant. J'ai consulté SO et n'ai pas trouvé de réponse exacte avec un code de démonstration, c'est pourquoi j'ai écrit cette réponse autant que je m'en souvienne. Si vous attendez une seule réponse et votez négativement chaque autre réponse, alors SO devrait interdire toutes les réponses autres que celles qui ont reçu une confirmation du propriétaire de la question.

0 votes

D'accord, je peux supprimer le vote négatif uniquement si vous modifiez la réponse. Donc lisez les autres réponses et expliquez pourquoi vous n'avez pas voulu utiliser ces solutions. Un wrapper (et en particulier un wrapper REF et OUT juste pour le plaisir). 5 personnes ont donné des réponses courtes et complètes avec des exemples, et seulement Eyal a essentiellement écrit : "Non, vous ne pouvez pas".

8voto

Eyal Schneider Points 11399

Java passe les paramètres par valeur et n'a aucun mécanisme pour permettre le passage par référence. Cela signifie que chaque fois qu'un paramètre est passé, sa valeur est copiée dans le cadre de pile gérant l'appel.

Le terme valeur tel que je l'utilise ici nécessite une petite clarification. En Java, nous avons deux types de variables - les primitifs et les objets. La valeur d'un primitif est le primitif lui-même, et la valeur d'un objet est sa référence (et non l'état de l'objet référencé). Par conséquent, toute modification de la valeur à l'intérieur de la méthode ne changera que la copie de la valeur dans la pile, et ne sera pas vue par l'appelant. Par exemple, il n'y a aucun moyen de mettre en œuvre une véritable méthode d'échange, qui reçoit deux références et les échange (pas leur contenu!).

6voto

James W Simms Points 1

Comme beaucoup d'autres, j'ai dû convertir un projet C# en Java. Je n'ai pas trouvé de solution complète sur le web concernant les modificateurs out et ref. Mais, j'ai pu utiliser les informations que j'ai trouvées et les développer pour créer mes propres classes afin de répondre aux besoins. Je voulais faire une distinction entre les paramètres ref et out pour la clarté du code. Avec les classes ci-dessous, c'est possible. Que ces informations fassent gagner du temps et des efforts à d'autres.

Un exemple est inclus dans le code ci-dessous.

//*******************************************************************************************
//CLASSE XOUT
//*******************************************************************************************
public class XOUT
{
    public XOBJ Obj = null;

    public XOUT(T value)
    {
        Obj = new XOBJ(value);
    }

    public XOUT()
    {
      Obj = new XOBJ();
    }

    public XOUT Out()
    {
        return(this);
    }

    public XREF Ref()
    {
        return(Obj.Ref());
    }
};

//*******************************************************************************************
//CLASSE XREF
//*******************************************************************************************

public class XREF
{
    public XOBJ Obj = null;

    public XREF(T value)
    {
        Obj = new XOBJ(value);
    }

    public XREF()
    {
      Obj = new XOBJ();
    }

    public XOUT Out()
    {
        return(Obj.Out());
    }

    public XREF Ref()
    {
        return(this);
    }
};

//*******************************************************************************************
//CLASSE XOBJ
//*******************************************************************************************
/**
 *
 * @author jsimms
 */
/*
    XOBJ est l'objet de base qui contient la valeur. XREF et XOUT sont des classes qui
    utilisent internement XOBJ. Les classes XOBJ, XREF et XOUT ont des méthodes qui permettent
    d'utiliser l'objet en tant que paramètre XREF ou XOUT; C’est important, car
    les objets de ces types sont interchangeables.

    Voir la méthode :
       XXX.Ref()
       XXX.Out()

    L'exemple ci-dessous montre comment utiliser XOBJ, XREF et XOUT ;
    //
    // Exemple de paramètre de référence
    //
    void AjouterAuTotal(int a, XREF Total)
    {
       Total.Obj.Value += a;
    }

    //
    // Exemple de paramètre out
    //
    void Ajouter(int a, int b, XOUT ParmOut)
    {
       ParmOut.Obj.Value = a+b;
    }

    //
    // Exemple XOBJ
    //
    int TestXObj()
    {
       XOBJ Total = new XOBJ<>(0);
       Ajouter(1, 2, Total.Out());    // Exemple d'utilisation du paramètre out
       AjouterAuTotal(1,Total.Ref()); // Exemple d'utilisation du paramètre ref
       return(Total.Value);
    }
*/

public class XOBJ {

    public T Value;

    public  XOBJ() {

    }

    public XOBJ(T value) {
        this.Value = value;
    }

    //
    // Méthode : Ref()
    // But : renvoie un objet de paramètre de référence en utilisant la valeur XOBJ
    //
    public XREF Ref()
    {
        XREF ref = new XREF();
        ref.Obj = this;
        return(ref);
    }

    //
    // Méthode : Out()
    // But : renvoie un objet de paramètre Out en utilisant la valeur XOBJ
    //
    public XOUT Out()
    {
        XOUT out = new XOUT();
        out.Obj = this;
        return(out);
    }

    //
    // Méthode get()
    // But : renvoie la valeur
    // Remarque : Comme il est fastidieux de modifier cela dans le code,
    // la valeur a été rendue publique
    //
    public T get() {
        return Value;
    }

    //
    // Méthode set()
    // But : définir la valeur
    // Remarque : Comme il est fastidieux de modifier cela dans le code,
    // la valeur a été rendue publique
    //
    public void set(T uneAutreValeur) {
        Value = uneAutreValeur;
    }

    @Override
    public String toString() {
        return Value.toString();
    }

    @Override
    public boolean equals(Object obj) {
        return Value.equals(obj);
    }

    @Override
    public int hashCode() {
        return Value.hashCode();
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X