2013-01-30 6 views
2

Il s'agit probablement d'une question de base, mais je ne suis pas sûr des mots-clés à utiliser pour la rechercher.Attribuer une valeur à une variable de retour en Java

Est-il possible d'attribuer une valeur à une variable de retour en Java, quelque chose comme ça:

static int a[] = new int[2]; 

static int f(int i) { 
    return a[i]; 
} 

static void main() { 
    f(1) = 0; // <-- this 
} 

en C/C++ je peux retourner un pointeur et d'attribuer une valeur plus tard. Puisque Java fonctionne avec des références, je m'attendrais à ce que le code ci-dessus fonctionne. Ai-je manqué un concept Java important ici?

+5

** Non, Non, Non **. Les références Java sont des références * non * C++. Ne confondez pas les deux. Les références Java sont plus proches des pointeurs C/C++ (sauf qu'elles sont traitées de manière opaque, déréférencées automatiquement et font toujours référence à un objet * valide *). –

+0

Les références Java sont transmises par valeur. Voir http://www.javadude.com/articles/passbyvalue.htm – Triztian

+0

@pst Euh, c'est exactement ce que dit Dimath dans la question, non? "En C/C++ je peux retourner un pointeur et lui assigner une valeur plus tard"? – melpomene

Répondre

5

Même s'il s'agit d'un type de référence, l'invocation de la méthode est et non une variable.

Cependant, quelque chose comme ça serait OK:

static MyClass func() { 
    return new MyClass(); 
} 

public static void main(String[] args) { 
    func().setAttr(null); // change attributes 
} 
+0

battu moi, @Desolator! @Dimath - Java décourage les techniques de manipulation de pointeurs globales hacky. envisager de refactoriser à un style orienté objet comme celui de cette réponse. – RubyTuesdayDONO

+0

+1 pour l'instruction "pas une variable" –

+0

@RubyTuesdayDONO (Nit: il n'y a pas de pointeur) –

0

Ceci est impossible (voir les autres commentaires), mais vous pouvez créer votre propre classe MutableInteger qui permet de modifier sa valeur:

public class MutableInteger { 
    public int value; 
    public MutableInteger(int value) { 
     this.value = value; 
    } 
    public MutableInteger() { 
     this(0); 
    } 
} 

static MutableInteger a[] = new MutableInteger[2]; 
static { 
    for (int i=0; i<a.length; i++) { 
     a[i] = new MutableInteger(); 
    } 
} 

static MutableInteger f(int i) { 
    return a[i]; 
} 

static void main() { 
    f(1).value = 0; // <-- this 
} 
+0

Le paramètre à f doit être int, pas MutableInteger, n'est-ce pas? – jfrank

+0

Oui, bien sûr. Fixé. J'étais dans un lieu de trouvaille. ;-) – bikeshedder

+0

'f (...)' a un type de retour de 'int' mais retourne un' MutableInteger'. ? –

0

Non. En Java, il n'y a que des types primitifs (qui se comportent principalement comme en C++) et des types de référence. Les types de référence se comportent comme un mélange entre les pointeurs C++ et les références C++: ils sont automatiquement déréférencés lorsque vous utilisez ., mais = modifie toujours la référence, et non la valeur de l'objet référencé.

0

Cela ne fonctionnera pas. Peut-être que cela aide à comprendre ce qui se passe au niveau "machine". A l'intérieur de la méthode f, l'expression a[i] est évaluée à une valeur int. Cette valeur int est renvoyée, sans aucune connexion au tableau associé à cette valeur. Après le retour de la méthode, vous avez la valeur int sur la pile d'opérandes de la machine virtuelle Java (pensez-y comme une valeur intermédiaire) et vous pouvez faire quelque chose avec elle. Vous pouvez le supprimer (ce qui arrive si vous écrivez f(1); sur une seule ligne), vous pouvez l'assigner à une variable (int x = f(1)), et c'est à peu près tout.

0

Une façon est de transformer votre tableau dans un tableau de MutableInt s (ou AtomicInteger s) et renvoyer une référence à l'i -ième élément de ce tableau:

static AtomicInteger a[] = new AtomicInteger[2]; 
static { 
    for (int i = 0; i < a.length; ++i) { 
     a[i] = new AtomicInteger(0); 
    } 
} 

static AtomicInteger f(int i) { 
    return a[i]; 
} 

public static void main(String[] args) { 
    f(1).set(0); 
} 
0

Ce sera une erreur de compilation parce que le Assignment Operator exige que le côté gauche soit un Expression Name, un Field Access Expression, ou un Array Access Expression, alors que f(1) est un Method Invocation Expression.

Erreurs de compilation mises à part, ce n'est pas comme cela que fonctionne Java. En Java, tout est transmis par valeur - particulièrement dans cet exemple particulier puisque votre type de retour est int.

static /*RETURN TYPE IS PRIMITIVE VALUE:*/ int f(int i) { 
    return a[i]; 
} 

Si l'on ajoute une variable intermédiaire, il devient plus clair:

static /*RETURN TYPE IS PRIMITIVE VALUE:*/ int f(int i) { 
    int ret = a[i]; // ret is an independent value from a[i] 
        // it and a[i] can be changed without affecting each other 
    return return ret; 
} 
0

La question de l'OP est

Est-il possible d'attribuer une valeur à une variable de retour en Java

Très simple ... (notez que j'affecte 10 pour montrer l'épreuve puisque toutes les valeurs sont 0 dans une init tableau ialised int) ...

static int a[] = new int[2]; 

static int f(int[] p, int index, int val) { 
    return p[index] = val; 
} 

static void main() {   
    // f(a, 1, 0); use 10 (below) so we can show proof 
    f(a, 1, 10); 
    // proof 
    System.out.println(a[1]); 
} 

... Un autre exemple stupide, mais fonctionne ...

static int a[] = new int[2]; 

static int[] f(int[] p) { 
    return p; 
} 

static void main() { 
    f(a)[1] = 10; 
} 

Encore une autre ...

static int a[] = new int[2]; 

static void f(int i, int val) { 
    a[i] = val; 
    return; 
} 

static void main() { 
    f(1, 10); 
} 
0

Vous pourriez être intéressé par comment lambdas peut être appliqué à ce problème, bien que cela ne fonctionne que dans l'aperçu Java 8.

Supposons qu'il y avait une interface définie comme celui-ci dans les bibliothèques standard:

interface Block<T> { 
    void accept(T v); 
} 

(Il a été proposé de mettre cela en java.util.functions, avec seulement un peu plus ajouté à la complexité ...)

maintenant, nous pouvons écrire votre exemple comme ceci:

// Declare an array 
int[] a = new int[5]; 

// Capture an "assignment reference" to element 2 
Block<Integer> elem2 = v -> a[2] = v; 

// Some time later, we want to store a new value in that element: 
elem2.accept(360); 

Ainsi, votre fonction retournerait Block<Integer>, sur lequel vous pouvez appeler plus tard accept pour lui donner une valeur à stocker.

Questions connexes