passing by reference ? czy to mozliwe w javie ?

passing by reference ? czy to mozliwe w javie ?
A8
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

witam, potrzebuje wysłać 2 zmienne do funkcji i je uaktualnić ale coś nie za bardzo mi to działa(cos podobnego chcę zaimplementować jak przekazywanie parametrow przez referencje lub wskaznik w cpp), proszę o pomoc, poniżej kawałek kodu:

Kopiuj
public class myclass {
	
    static int currentMonth = 0;
	static int MonthToSet = 0;
		
	public static void abc() 
	{
		
		currentMonth = 4; //<----
		MonthToSet = 4; // <----

    }
        ......
	public static void main(String[] args) {

    abc();
        
       

czy w javie tak sie da? pozdrawiam

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5549
3

Nie, w Javie nie ma przekazywania przez referencję. Ani przez wskaźnik. Można zrobić przekazywanie przez obiekt wrapujący. albo zwrócić wartość w "tupli" lub rekordzie.
BTW na razie to przekazujesz przez zmienne statyczne 🙁

A8
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6
0

zrobiłem to tak:

Kopiuj

class date
{ 
  public int currentMonth; 
  public int MonthToSet;
  public date(int currentMonth, int MonthToSet) 
  { 
  this.currentMonth = currentMonth; 
  this.MonthToSet = MonthToSet;
  } 
} 
public static void main(String[] args) 
{
  date mydateValue = new date(0,0); 
  boolean forward = searchForward(driver, date, mydateValue); //<----------------------------

w tej funkcji updejtuje klase date i działa, to jest przez obiekt wrapujący tak jak napiałeś?

Manna5
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 667
1

Można też przekazywać wskaźnik tworząc zmienne jako jednoelementowe tablice:

Kopiuj
public class Przyklad
{
  private static void zamien (int a[], int b[])
  {
    int pom;

    pom = a[0];
    a[0] = b[0];
    b[0] = pom;
  }

  public static void main (String args[])
  {
    int[] e, f;

    e = new int[1];
    f = new int[1];
    /* Tylko NIE e = f = new int[1]!!! */
    e[0] = 123;
    f[0] = 456;

    System.out.println ("PRZED: e=" + e[0] + " f=" + f[0]);
    zamien (e, f);
    System.out.println ("PO: e=" + e[0] + " f=" + f[0]);
  }
}
Charles_Ray
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1909
2

Nie da się tego zrobić i to akurat bardzo dobrze. Metoda nie powinna zmieniać stanu dookoła, ponieważ taki kod jest (1) trudny do przetestowania i (2) nieczytelny. Poczytaj o niemutowalności i “side effects”. Jak już potrzebujesz coś jednak modyfikować, to musisz przekazać referencje do obiektu, którego pola będziesz zmieniać.

KE
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 757
0

Nie da się tego zrobić i to akurat bardzo dobrze.

Miałem właśnie flashback z poprzedniego projektu, w którym ubersenior z rozdmuchanym ego prawił swoje tezy w taki sposób. Nie pochwalam tego.

Jak już potrzebujesz coś jednak modyfikować, to musisz przekazać referencje do obiektu

Dokładnie, to jest rozwiązanie. Stworzyć obiekt swojej klasy, trzymający stan który nas interesuje, i przekazywać go dalej. To może być nieczytelne i trudne w testowaniu, ale nie musi. Kwestia implementacji.

Można też przekazywać wskaźnik tworząc zmienne jako jednoelementowe tablice:

To jest bardzo brzydki hack, warto zrobić jednak swoją klasę z sensowną nazwą i tam mieć nawet ten znienawidzony setter. Ta sztuczka ma sens tylko w przypadku Streamów, gdzie czasem chciałoby się odłożyć coś na bok, ale Java nie pozwala ze względu na to jak działają lambdy pod spodem, więc robi się taki twór.

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5549
1
kelog napisał(a):

Nie da się tego zrobić i to akurat bardzo dobrze.

Miałem właśnie flashback z poprzedniego projektu, w którym ubersenior z rozdmuchanym ego prawił swoje tezy w taki sposób. Nie pochwalam tego.

pierwsze zdanie można uznać za luźny cytat z projektowania Javy. Java nie ma przekazywania przez referencję nie dlatego że nie umieli tego zrobić tylko uważali że przekazywanie przez referencję to zło. a czy twórcy javy mieli rozdmuchane ego? Oczywiście. legenda mówi że compilatory C1 i C2 powstały jako osobne projekty bo dwóch uber seniorów nie umiało się dogadać i zamkneli się w osobnych pokojach ze swoimi zespołami. w rezultacie jeden zrobił kompilator który kompiluje szybko ale generował wolny kod a drugi zrobił kompilator który kompiluje wolno ale generuje szybki kod. jakby to robili jak normalni to były jeden kompilator z flagami kompilacji. oczywiście potem zostało to przykryte flagami kompilacji itd

Kapustka
  • Rejestracja: dni
  • Ostatnio: dni
0

Wracając do pierwszego pytania,
@Adam8877 da się tak w Javie i kod który podałeś powinien zadziałać.

1. Bez przekazania

Pełna wersja tego co napisałeś mogłaby wyglądać tak:

Kopiuj
class Main {
  public static int month;
  public static void main(String[] args) {
    MyClass.changeMonth();
    System.out.println(month); // wynik: 4
  }
}

class MyClass {
  public static void changeMonth() {
    Main.month = 4;
  }
}

W takim podejściu nie ma przekazywania, changeMonth nic nie otrzymuje, tylko sam sięga do Main i zmienia.
Gdy taki kod ci się rozrośnie, możesz być zdezorinetowany, jaki fragment, kiedy i dlaczego zmienia Main.month.
I wtedy możesz uznać, że lepiej będzie tę zmianę wyraźniej wyrazić w kodzie, przekazując month do changeMonth np.

2. Przekazanie przez wartość

Kopiuj
class Main {
  public static void main(String[] args) {
    int month = 0;
    MyClass.changeMonth(month);
    System.out.println(month); // wynik: 0
  }
}

class MyClass {
  public static void changeMonth(int month) {
    month = 4;
  }
}

Ta wersja nie zadziała jak byś chciał. Typy proste w Javie przekazywanie są przez wartość.
Month widoczny w ciele changeMonth to niezależna kopia month z main i zmiana nie będzie widoczna w main.
Natomiast przez referencję przekazywane są w Javie obiekty, stąd poniższa wersja zadziała ok.

3. Przekazanie przez referencję

Kopiuj
class Main {
  public static void main(String[] args) {
    var month = new MyInteger();
    MyClass.changeMonth(month);
    System.out.println(month.value); // wynik: 4
  }
}

class MyInteger {
  public int value;
}

class MyClass {
  public static void changeMonth(MyInteger month) {
    month.value = 4;
  }
}

W praktyce zamiast MyInteger nazwiemy klasę inaczej, bliżej problemu i powiększymy o więcej pól...

Podsumowując:
Tak jak napisałeś się da, przy czym to jest bez przekazania.
I tak, w Javie jest przekazanie przez referencję (argumentów obiektowych).

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.