Jak zrobić odpowiednik pass by reference dla primitives w Javie

Ten kod Javy:

public class XYZ {   
    public static void main(){  
        int toyNumber = 5;   
        XYZ temp = new XYZ();  
        temp.play(toyNumber);  
        System.out.println("Toy number in main " + toyNumber);  
    }

    void play(int toyNumber){  
        System.out.println("Toy number in play " + toyNumber);   
        toyNumber++;  
        System.out.println("Toy number in play after increement " + toyNumber);   
    }   
}  

Wyświetli to:

 
Toy number in play 5  
Toy number in play after increement 6  
Toy number in main 5  

W C++ mogę przekazać zmienną toyNumber jako pass by reference, aby uniknąć cieniowania tj. tworzenia kopii tej samej zmiennej jak poniżej:

void main(){  
    int toyNumber = 5;  
    play(toyNumber);  
    cout << "Toy number in main " << toyNumber << endl;  
}

void play(int &toyNumber){  
    cout << "Toy number in play " << toyNumber << endl;   
    toyNumber++;  
    cout << "Toy number in play after increement " << toyNumber << endl;   
} 

I wyjście C++ będzie takie:

Toy number in play 5  
Toy number in play after increement 6  
Toy number in main 6  

Moje pytanie brzmi-jaki jest równoważny kod w Javie, aby uzyskać taki sam wynik jak kod C++, biorąc pod uwagę, że Java jest pass by value, a nie pass by reference ?

Author: Community, 2011-04-11

6 answers

Masz kilka możliwości. Ten, który ma największy sens, zależy od tego, co próbujesz zrobić.

Wybór 1: make toynumber Public member variable in a class

class MyToy {
  public int toyNumber;
}

Następnie podaj odniesienie do MyToy do swojej metody.

void play(MyToy toy){  
    System.out.println("Toy number in play " + toy.toyNumber);   
    toy.toyNumber++;  
    System.out.println("Toy number in play after increement " + toy.toyNumber);   
}

Wybór 2: Zwraca wartość zamiast pass by reference

int play(int toyNumber){  
    System.out.println("Toy number in play " + toyNumber);   
    toyNumber++;  
    System.out.println("Toy number in play after increement " + toyNumber);   
    return toyNumber
}

Ten wybór wymagałby małej zmiany miejsca wywołania w main tak, aby brzmiało, toyNumber = temp.play(toyNumber);.

Wybór 3: uczyń to klasą lub zmienna statyczna

Jeśli obie funkcje są metodami tej samej klasy lub instancji klasy, można przekonwertować toyNumber na zmienną klasy.

Wybór 4: Utwórz tablicę pojedynczych elementów typu int i przekaż

Jest to uważane za hack, ale czasami jest używane do zwracania wartości z inline class invocations.

void play(int [] toyNumber){  
    System.out.println("Toy number in play " + toyNumber[0]);   
    toyNumber[0]++;  
    System.out.println("Toy number in play after increement " + toyNumber[0]);   
}
 162
Author: laslowh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 16:52:35

Java nie jest wywołaniem przez referencję jest to wywołanie tylko przez wartość

Ale wszystkie zmienne typu object są w rzeczywistości wskaźnikami.

Więc jeśli użyjesz Mutowalnego obiektu, zobaczysz zachowanie, które chcesz

public class XYZ {

    public static void main(String[] arg) {
        StringBuilder toyNumber = new StringBuilder("5");
        play(toyNumber);
        System.out.println("Toy number in main " + toyNumber);
    }

    private static void play(StringBuilder toyNumber) {
        System.out.println("Toy number in play " + toyNumber);
        toyNumber.append(" + 1");
        System.out.println("Toy number in play after increement " + toyNumber);
    }
}

Wyjście tego kodu:

run:
Toy number in play 5
Toy number in play after increement 5 + 1
Toy number in main 5 + 1
BUILD SUCCESSFUL (total time: 0 seconds)

To zachowanie można zobaczyć również w bibliotekach standardowych. Na przykład Kolekcje.sort (); Kolekcje.shuffle(); Metody te nie zwracają nowej listy, lecz modyfikują obiekt argumentu.

    List<Integer> mutableList = new ArrayList<Integer>();

    mutableList.add(1);
    mutableList.add(2);
    mutableList.add(3);
    mutableList.add(4);
    mutableList.add(5);

    System.out.println(mutableList);

    Collections.shuffle(mutableList);

    System.out.println(mutableList);

    Collections.sort(mutableList);

    System.out.println(mutableList);

Wyjście ten kod:

run:
[1, 2, 3, 4, 5]
[3, 4, 1, 5, 2]
[1, 2, 3, 4, 5]
BUILD SUCCESSFUL (total time: 0 seconds)
 25
Author: Kerem Baydoğan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-17 21:24:30

Make A

class PassMeByRef { public int theValue; }

Następnie podaj odniesienie do jego instancji. Zauważ, że metoda, która mutuje stan poprzez swoje argumenty, jest najlepiej unikać, zwłaszcza w kodzie równoległym.

 14
Author: Ingo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-11 09:55:29

W Javie nie można przekazać prymitywów przez odniesienie. Wszystkie zmienne typu object są oczywiście wskaźnikami, ale nazywamy je "referencjami", a także zawsze są przekazywane przez wartość.

W sytuacji, gdy naprawdę musisz przekazać wartość primitive by, ludzie czasami będą deklarować parametr jako tablicę typu primitive, a następnie przekazywać tablicę jednoelementową jako argument. Więc przekazujesz referencję int [1], a w metodzie możesz zmienić zawartość / align = "left" /

 10
Author: Ernest Friedman-Hill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 20:44:50

Dla szybkiego rozwiązania, możesz użyć AtomicInteger lub dowolnej ze zmiennych atomowych, które pozwolą Ci zmienić wartość wewnątrz metody za pomocą wbudowanych metod. Oto przykładowy kod:

import java.util.concurrent.atomic.AtomicInteger;


public class PrimitivePassByReferenceSample {

    /**
     * @param args
     */
    public static void main(String[] args) {

        AtomicInteger myNumber = new AtomicInteger(0);
        System.out.println("MyNumber before method Call:" + myNumber.get());
        PrimitivePassByReferenceSample temp = new PrimitivePassByReferenceSample() ;
        temp.changeMyNumber(myNumber);
        System.out.println("MyNumber After method Call:" + myNumber.get());


    }

     void changeMyNumber(AtomicInteger myNumber) {
        myNumber.getAndSet(100);

    }

}

Wyjście:

MyNumber before method Call:0

MyNumber After method Call:100
 9
Author: premSiva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 16:39:57
public static void main(String[] args) {
    int[] toyNumber = new int[] {5};
    NewClass temp = new NewClass();
    temp.play(toyNumber);
    System.out.println("Toy number in main " + toyNumber[0]);
}

void play(int[] toyNumber){
    System.out.println("Toy number in play " + toyNumber[0]);
    toyNumber[0]++;
    System.out.println("Toy number in play after increement " + toyNumber[0]);
}
 2
Author: itun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 20:50:14