Arrays.copyof

0

znalazlem takie wytlumaczenie co to robi: "copyOf() - pozwoli skopiować całość lub fragment tablicy, do innej tablicy. W przypadku typów obiektowych kopiowane są referencje (nie są tworzone kopie obiektów), więc modyfikując obiekty w jednej tablicy, zmodyfikujemy także obiekty w utworzonej kopii"
Jednak gdy przetestowalem to w taki sposob:

Integer[] i = { 5, 4, 3, 2, 1 };
		Integer[] i2 = new Integer[i.length];
		i2 = Arrays.copyOf(i, i.length);
		i[0] = 21212;

		for (int num : i) {
			System.out.print(num + " ");
		}
		System.out.println();
		for (int num : i2) {
			System.out.print(num + " ");
		}

to druga tablica nie zmienila swojej pierwszej wartosci jak mam to rozumiec? bo ja rozumiem definicje tej metody "copyof" tak , ze 2 tablice wskazuja na ta sama referencje tak? Wiec skoro wskazuja na ta sama referencje to jak zmienimy w 1 tablicy jakas wartosc to i w 2 tablicy powinna sie zmienic?czy jednak nie wskazuja na ta sama referencje?
bo wedlug mnie to powinno dzialac tak jak to:

Integer[] i = {5,4,3,2,1};
    Integer[] i2 = new Integer[i.length];
    i2 = i;
    //Arrays.sort(i2);
    i[0] = 21212;
    for(int num: i2) {
        System.out.print(num + " ");
    }
     
    System.out.println();
     
    for(int num: i) {
        System.out.print(num + " ");
    }

Pozdrawiam

1

Trochę nie zrozumiałeś - pierwsza tablica nie jest połączona z drugą - referencje są kopiowane co oznacza, że jeżeli byś miał

ObiektZPolem] tablica = new ObiektZPolem [1];
tablica[0] = new ObiektZPolem(0);
ObiektZPolem[] kopia = Arrays.copyOf(tablica, 1);

to wtedy

tablica[0].pole = 5;
System.out.println(kopia[0].pole) //Zwraca 5

same tablice to tylko kawałek pamięci z 'wskaźnikami` 'po kolei', więc jeżeli zmienisz to co jest pod 'wskaźnikiem', to uzyskując do niego dostęp z innego miejsca zobaczysz zmianę.

1

Aha. Dodałbym jeszcze, że na tablicy z obiektami typu Integer nie da się tego zaobserwować, bo obiekt Integer jest niezmienny (immutable). Żadna z metod tej klasy nie pozwala zmienić wartości wewnętrznej typu int, która siedzi tam w środku. Chociaż...

public class MutableInt
{

  public static void main(String args[])
    throws NoSuchFieldException, IllegalAccessException
  {
    Integer[] array = new Integer[1];
    array[0] = new Integer(5);
    Integer[] array2 = java.util.Arrays.copyOf(array, 1);
    System.out.println("w kopii jest " + array2[0]
      + ", a w oryginale: " + array[0]);
    for (java.lang.reflect.Field f: Integer.class.getDeclaredFields()) {
      System.out.println("field " + f);
    }
    java.lang.reflect.Field field = Integer.class.getDeclaredField("value");
    field.setAccessible(true);
    field.setInt(array2[0], 3);
    System.out.println("w kopii jest " + array2[0]
      + ", a w oryginale: " + array[0]);
  }

}

W wyniku pisze:

w kopii jest 5, a w oryginale: 5
field public static final int java.lang.Integer.MIN_VALUE
field public static final int java.lang.Integer.MAX_VALUE
field public static final java.lang.Class java.lang.Integer.TYPE
field static final char[] java.lang.Integer.digits
field static final char[] java.lang.Integer.DigitTens
field static final char[] java.lang.Integer.DigitOnes
field static final int[] java.lang.Integer.sizeTable
field private final int java.lang.Integer.value
field public static final int java.lang.Integer.SIZE
field public static final int java.lang.Integer.BYTES
field private static final long java.lang.Integer.serialVersionUID
w kopii jest 3, a w oryginale: 3

Czasem musimy tak oszukać, np. w czasie pisania testów.

0

Czyli po uzyciu Arrays.copyOf na innych obiektach np Person itp stworzonych przez nas to wskazuje ta kopia na ta sama referencje i po zmianie wartosci np 1 elementu tablicy zarowno w kopii jak i w oryginale sie zmieni ta wartosc, a jezeli zrobimy Arrays.copyOf np na Integer albo String to juz wskazuje na inna referencje i dlatego po zmianie jakiegos elementu w tablicy kopii w glownej tablicy sie nic nie zmieniaja tak?

0

Ta linijka:
i[0] = 21212;
Wstawia na początek tablicy i referencję do dużego Integera. Poprzedni Integer jest jednak niezmieniony. Integery są niemutowalne, w środku mają takie pole:

/**
     * The value of the {@code Integer}.
     *
     * @serial
     */
    private final int value;

By zmienić zawartość Integera musiałbyś podmienić mu wartość pola value.

edit:
Nie doczytałem poprzedniej odpowiedzi - @jarekczek w sumie napisał to samo.

Czyli po uzyciu Arrays.copyOf na innych obiektach np Person itp stworzonych przez nas to wskazuje ta kopia na ta sama referencje i po zmianie wartosci np 1 elementu tablicy zarowno w kopii jak i w oryginale sie zmieni ta wartosc, a jezeli zrobimy Arrays.copyOf np na Integer albo String to juz wskazuje na inna referencje i dlatego po zmianie jakiegos elementu w tablicy kopii w glownej tablicy sie nic nie zmieniaja tak?
Najpierw musisz zrozumieć różnicę między: `a.b = new B()` a `a.b.c = new C()` bo mniej więcej to wszystko się do tego sprowadza. Załóżmy, że tablica ma ponazywane pola, tzn jest obiektem typu: ```java class Array3 { Integer _0; Integer _1; Integer _2; } ``` Powyższa klasa zachowuje się podobnie jak tablica 3-elementowa, tzn: ```java Integer[] array = new Integer[3]; array[0] = 5; ``` zachowuje się mniej więcej tak samo jak: ```java Array3 array = new Array3(); array._0 = 5; ``` Linijka `array._0 = 5;` podmienia zawartość tablicy, ale nie podmienia zawartości Integera. By podmienić zawartość Integera musiałbyć zrobić mniej więcej: ```array._0.value = 5;``` bądź analogicznie: ```array[0].value = 5``` Ale tak nie zrobisz, bo Integery są niemutowane - dostęp do pola `value` jest zabroniony i nie ma metod by to pole zmienić.

Aktualizacja:
Albo jeszcze inaczej.
i[0] = 21212;
podlega autoboxingowi, a autoboxing działa tak:

Integer box(value: int): Integer = {
  if (value >= -128 && value <= 127) {
    return IntegersCache[value + 128];
  } else {
    return new Integer(value);
  }
}

i ostatecznie instrukcja po autoboxingu wygląda tak:
i[0] = box(21212);

0

Niestety nadal nie rozumiem , przeciez jak mamy:

Integer a = 4;
a  =5;

To zmienia sie Integer.

0

Czyli jak robie : Integer a = 6; <--- 1 obiekt
a = 5; <---- drugi obiekt?
a ten 1 nadal zostaje w pamieci?

1

Zauważ, że zarówno 5 jak i 6 mają typ int, a nie Integer. W Javie 5 wprowadzono autoboxing, który jest opisany tutaj: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

W skrócie przed Javą 5 taki kod:

Integer x = 5;

skutkował błędem kompilacji. Po wprowadzeniu autoboxingu powyższy kod jest zamieniany automatycznie na coś co zachowuje się mniej więcej jak poniższy kod:

Integer x = Integer.valueOf(5);

przy czym ZTCW wbudowane w Javę 5 mechanizmy (nowy opkod w bajtkodzie) są szybsze niż wywołanie tej metody.

0

a to jak zrobie tak:

Integer a = 4;
a = 3;

to garbage colector i tak usunie obiekt a? czy bedzie trzymal?

1

Nie do końca, ale to wynika z tego że Integery są wrzucane do puli obiektów, czyli jeśli będzie jakaś wartość integera to JVM będzie to przechowywać i inne Integery mające tą sąmą wartośc będą de facto referencją na ten sam obiekt.
Dla przykładu

       int int1 = 5;
       Integer integer1 = 5;
       Integer integer2 = 5;

       Integer integer3 = 2;
       Integer integer4 = 3;
       Integer integer5 = integer3 + integer4;

       System.out.println("int1 == integer2 = " + (int1==integer2));
       System.out.println("integer1 == integer2 = " + (integer1==integer2));
       System.out.println("integer1 == integer5 = " + (integer1==integer5));

Zwróci:
int1 == integer2 = true
integer1 == integer2 = true
integer1 == integer5 = true

Obiekty Integer tak jak String nie są zarządzane w ten sam sposób co inne obiekty Javove, chociaż przyznam że tu nie czuję się mocno, lepiej @Koziołek albo @Shalom to wytłumaczą :)

0

oki a jak zrobimy cos takiego:

private Person[] persons;
	private int emptyPlace;

	PersonDatabase()
	{
		setPersons(new Person[getINITIAL_CAPACITY()]);
		setEmptyPlace(0);
	}
	public void add(Person p)
	{
		if(getEmptyPlace() ==getINITIAL_CAPACITY())
		{
			persons = Arrays.copyOf(persons,getINITIAL_CAPACITY()*2);
			
		}
	}

tutaj fragment zadanka jest, wiec jezeli puste miejsce bedzie sie rownalo poczatkowej pojemnosci to tablica persons zwieksza swoja pojemnosc 2 razy przy uzyciu kompii, a tamten obiekt wczesniejszy caly czas obciaza pamiec tak? ten przed 2krotnym zwiekszeniem? i jak bedziemy tak zwiekszac duzo razy to tamte obiekty caly czas zostaja w pamieci? i jezeli tak to czy garbage colector je wyczysci?

1 użytkowników online, w tym zalogowanych: 0, gości: 1