Więc jestem nowy w Javie.

Napotkałem to pytanie podczas wykonywania ćwiczeń.

enter image description here

Moje rozwiązanie

public static void fillWithRandomNumbers (double[] values) {

    double[] numbers = new double[values.length];

    for(int i = 0 ; i < numbers.length ; i++){

    numbers[i] = Math.random();
    values[i] = numbers[i];                  // <---- That's the only thing I changed from the above code.

    }

}

Od czasu mojej wykładu, stwierdza to.

W Javie operator przydziałowy może być używany do kopiowania zmiennych typu danych prymitywnych, ale nie ma tablic.

enter image description here

Ale kiedy próbowałem uruchomić kod napisany w powyższym pytaniu i wydrukuj wyniki. Daje mi pełną liczbę losową.

Wynik

--------------------Configuration: Test - JDK version 1.8.0_171 <Default> - <Default>--------------------
0.5879563734452546
0.18409227033985642
0.7866217402158342
0.8023851737037745
8.892207358659476E-4
0.8614310541417136
0.6907363995600082
0.8974247558057734
0.4294464665985942
0.19879131710939557

Process completed.

Pełny kod z powyższego wyjścia.

public class Test {

   public static void main(String[] args) {

    double[] test = new double[10];

    fillWithRandomNumbers(test);


   }



   public static void fillWithRandomNumbers(double[] values){

    double[] numbers = new double[values.length];

    for(int i = 0 ; i < numbers.length ; i++){

    numbers[i] = Math.random();
    values = numbers;
    System.out.println(values[i]);

    }

 }


}

Moje pytania brzmi: jak to możliwe? Ponieważ w notatkach stwierdził, że zawartość tablicy nie może zostać skopiowana przez bezpośrednie przypisywanie między tablicami. Dotyczy to również C, jeśli się nie mylę.

A także moje rozwiązanie jest poprawne? Chcę tylko zrozumieć, jak i dlaczego jest to możliwe?

0
Cash- 2 czerwiec 2018, 21:14

3 odpowiedzi

Najlepsza odpowiedź

Przypisanie tablicy.

values = numbers;

Spowoduje zmienną values, aby odnosić się do tablicy numbers, czyli kopie odniesienia.

Jednak zmienna values jest parametrem do metody i ma zamiar wyjść z zakresu. Więc przypisany jest odniesienie, który ma zostać wyrzucony. Java jest ściśle językiem przechodzącej wartością. Po przekazaniu odniesienia do tablicy do sposobu, wartość tego odniesienia (zasadniczo, wskaźnik) jest przekazywany do metody według wartości. Tak więc w oryginalnym kodzie na górze, tablica dzwoniące pozostanie niezmieniona, a nowa tablica liczb losowych (wskazała na zarówno values i numbers zmienne właśnie wcześniejsze do zakończenia metody, ale nie wskazywał niczego po) stanie się śmieci i będzie zebrany na śmieci i zagubiony.

Jeśli chcesz nowej tablicy z liczbami losowymi, które należy zachować, zwróć go z metody. Z drugiej strony, jeśli chcesz aktualizować tablicę dzwoniącego, może może kopiować każdy element z numbers z powrotem do values, ale łatwiej byłoby po prostu wygenerować Losowe liczby w values, aby rozpocząć się z (a następnie nie ma potrzeby w ogóle numbers tablicy):

for (int i = 0; i < values.length; i++) {
    values[i] = Math.random();
}

Nazwa metody, fillWithRandomNumbers, naprawdę sugeruje, że ta ostatnia operacja jest tego, czego jest pożądana i oczekiwana przez dzwoniącego.

Zobacz także jest Java "Pass-Reference" lub "Pass -BE-WARTOŚĆ "?.

1
David Conrad 2 czerwiec 2018, 18:47

Nie kopiujesz tablicy. Odwołujesz się jedynie tym samym obiektem w pamięci. Wyobraź sobie, jeśli masz tablicę x= [1 , 2, 3, 4]; i mówisz y = x; y i x są wskazujące na tę samą przestrzeń w pamięci. Więc jeśli zmienię wartość w x, zmienia wartość w y. Nie ma kopiowania, ale zamiast tego samego dokładnego obiektu. Jeśli dodam wartość do x, będzie odzwierciedlone w y.

double[] x = new double[10];

double[] y = x;

x[0] = 2.0;

x[0] == y[0] //Will be true

double[] numbers = new double[values.length];

for(int i = 0 ; i < numbers.length ; i++)
{

  numbers[i] = Math.random();
  values[i] = numbers[i];
}
0
Eddie D 2 czerwiec 2018, 18:40

Twoje notatki mówią:

W Javie operator przydziałowy może być używany do kopiowania prymitywnych zmiennych typu danych, ale nie macierzy.

To, co oznacza, że nie można zrobić głębokiej kopii innej tablicy z operatorem przypisywania. Co robi operator przydziałowy, ma płytką kopię w porównaniu z głęboką kopią. Jakie są płytkie kopie i głębokie kopie? Cóż, wszystkie dane istnieją w pamięci. Kiedy tworzymy tablicę x, jest przypisany lokalizację pamięci, powiedzmy 0x1000 (lokalizacja nie ma znaczenia). Jeśli weźmiemy kolejną zmienną y i przypisz ją x: (y = x), co to robi, nie jest kopiowanie wszystkich wartości w {x5}}, kopiuje tę lokalizację pamięci {{x6 }}. Więc teraz x i y odnoszą się do tego samego miejsca w pamięci. Nazywa się to płytką kopią. Jeśli zmienamy wartość w x: {{x10}} {{x11}}, {{x11}} otrzymuje tak dobrze ({{x12}} // 4!). y nie jest niezależną kopią. Kiedy kopiujemy prymitywy, otrzymujemy wartość, którą zmienna reprezentuje, a nie lokalizacja pamięci. dawny:

x = 5;
y = x;
y = 2;
// x equals 5 and y equals 2. changing the value of y did not change the value of x!

Jeśli chcesz zrobić głęboką kopię, zrobiłbyś coś takiego:

for(int i=0; i < numbers.length; i++){
    numbers[i] = Math.random();
    values[i] = numbers[i];
}

Teraz, jeśli zmienisz wartość liczbami, nie zmieni wartości w wartościach. dawny:

System.out.println(numbers[0]) // 0.5879563734452546
numbers[0] = 1.2;
System.out.println(values[0]) // 0.5879563734452546
0
Nemo 2 czerwiec 2018, 21:03