Zagadka Java #4

Zagadki Java zawierają różnego rodzaju niuanse języka i „podchwytliwe” fragmenty kodu. Każda następna zagadka będzie zawierała odpowiedź i wyjaśnienie do poprzedniej. Lista wszystkich zagadek.

Jeżeli znasz odpowiedź, podziel się nią w komentarzu!

Zagadka Java #4

Jaki, oraz dlaczego, będzie wynik uruchomienia poniższej klasy?

import java.util.Arrays;
import java.util.List;

public class TabToList {
  public static void main(String[] args) {
    Integer[] tab = { 1, 10, 100 };
    List<Integer> list = Arrays.asList(tab);

    // zmień wartość pierwszego elementu listy
    list.set(0, 5000);

    System.out.println(tab[0]);
    System.out.println(list.get(0));

    list.add(111);

    // wyświetl wartość ostatniego elementu listy
    System.out.println(list.get(list.size() - 1));
  }
}

Odpowiedź do poprzedniej zagadki #3

Poniżej znajdziesz odpowiedź do poprzedniej zagadki.

W wyniku uruchomienia klasy JustMain, na ekranie zobaczymy:

MyCat is eating lasagne MyCat is eating lasagne MyCat is eating lasagne Parent's favorite food: salmon Grandparent's favorite food: unknown

Wynika z tego, że jeżeli klasy w hierarchii dziedziczenia posiadają pole o takiej samej nazwie, to możemy odnieść się do tego pola w konkretnej klasie, rzutując this na obiekt tej klasy:

((Cat) this).favoriteFood
((Animal) this).favoriteFood

W pierwszym przypadku rzutujemy this na obiekt klasy bazowej (MyCat dziedziczy po Cat). W drugim przypadku, rzutujemy this na klasę bazową klasy Cat (Cat dziedziczy po Animal). Dzięki temu zapisowi, odniesiemy się, odpowiednio, do pola favoriteFood z klasy Cat, oraz z klasy Animal. Tworzenie pól o takich samych nazwach w klasach podrzędnych może nie mieć dużego sensu, ale warto znać tę właściwość dziedziczenia.

Ten sam mechanizm nie zadziała w przypadku wywoływania metod – każda z poniższych linii:

this.eat();
((Cat) this).eat();
((Animal) this).eat();

Spowoduje wywołanie metody eat z klasy MyCat, o czym świadczy pierwsza część wyniku działania klasy JustMain:

MyCat is eating lasagne MyCat is eating lasagne MyCat is eating lasagne

Dzieje się tak, ponieważ, w przypadku metod, mamy do czynienia z mechanizmem method overriding (nadpisywanie metod). To, która metoda zostanie wywołana, zależy od faktycznego typu obiektu, którym jest obiekt wskazywany przez this. Rzutowanie na jedną z klas w hierarchii dziedziczenia nie ma, w przypadku metod, efektu.

Więcej na ten temat możesz przeczytać w oficjalnej specyfikacji języka Java.

Komentarze (3):

  1. Przepraszam poprzedni komentarz zawiera błędy, które dopiero teraz zauważyłem,
    na początku powinno być oczywiście List list = Arrays.asList(tab)
    oraz fragment ... zmienia się również wartość elementu tab[index]. Należy dodać, że oba odwołania wskazują na ten sam element w pamięci.
    Chcąc uzyskać zamierzony cel należałoby zmienić wyrażenie List list = Arrays.asList(tab) na List list = new ArrayList(Arrays.asList(tab));
    W efekcie program wykona się bezbłędnie i otrzymamy zamierzony wynik:
    1
    5000
    111

    Poproszę o krytyczne uwagi i serdecznie pozdrawiam

  2. List list = Arrays.asList(Integer[] tab) - jest statyczną metodą zwracającą referencję do listy elementów tablicy będącej jej argumentem. Lista ta ma stały rozmiar (fixed-size) zatem nie posiada zdefiniowanych metod add() oraz remove(). Do elementów tej listy można odwoływać się poprzez index tak jak do tablicy, używając metody list.set(index, value) oraz list.get(index) zwracającej wartość o podanym indeksie. Ponieważ zmienna list zawiera referencję do tablicy tab to zmiana wartości elementu listy list.set(index, value) zmienia również wartość elementu array[index].
    Podsumowując przedstawiony powyżej fragment programu skompiluje się, w wyniku wykonania otrzymamy wyniki:
    5000
    5000
    a następnie w linii zawierającej instrukcję list.add() zostanie wygenerowany wyjątek UnsupportedOperationException

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Nie musisz podawać swojego imienia, e-mailu, ani strony www, aby opublikować komentarz. Komentarze muszą zostać zatwierdzone, aby były widoczne na stronie.