Tworzenie listy

W9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 132
0

Czy tworząc listę np w klasie MyClass

lepiej tworzyć taką listę od razu przy deklaracji pola w klasie MyClass,

Kopiuj
private LinkedList<String> myList = new LinkedList<>();

czy tworzyć najpierw pole

Kopiuj
private LinkedList<String> myList;

i dopiero w konstruktorze MyClass tworzyć nowy obiekt i przypisac do zmiennej

Kopiuj
MyClass(){
myList = new LinkedList<>();
}

Moim daniem druga opcja lepsza, ale nie jestem w stanie wytłumaczyć dlaczego.
A więc która opcja lepsza i dlaczego ?

jarekr000000
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: U krasnoludów - pod górą
  • Postów: 4712
1

Oba podejścia są złe. Z tym, że inicjalizacja pola od razu jest złem mniejszym.
Dlaczego,
bo przynajmniej nie masz sytuacji, że w polu pozostaje jakiś null, który może zostać przypadkiem zapomniany. Można zapomnieć jeśli napiszesz kolejny konstruktor.

Jak to zrobić lepiej:
dodać modyfikator final.

private final LinkedList<String> myList
Wtedy czy to w konstruktorze czy w polu inicjujemy - kompilator zadba abyśmy to zrobili.

Da się to jeszcze lepiej zrobić, ale to kolejny poziom.

Spine
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6968
2

Ja wolę pierwszy sposób. Nie przepisujemy niepotrzebnie nazwy zmiennej.

W konstruktorze najlepiej tworzyć listę lub pobierać ją jako parametr, jeśli chcemy użytkownikom danej klasy pozwolić na taki wybór. Ja wszystkie pola, które nie są parametrem konstruktora inicjuję w ciele klasy, o ile jest to możliwe.

W9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 132
0
jarekr000000 napisał(a):

Da się to jeszcze lepiej zrobić, ale to kolejny poziom.

Jak to zrobić jeszcze lepiej ?

jarekr000000
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: U krasnoludów - pod górą
  • Postów: 4712
3

Poziomy zła takie są:

  1. finalne pole (niezmienna) do niemutowalnego obiektu. W zasadzie ideał.
    W praktyce oczywiście to powinno wyglądać mniej więcej tak:
Kopiuj
final io.vavr.collection.List<String>  myList;

MyClass (params)  {
   myList = .... list initialization  from params.
}

Jedynie słuszne podejście w programowaniu funkcyjnym.

  1. dużo gorzej:
    referencja (zmienna ) do niemutowalnej klasy
    io.vavr.collection.List<String> myList = ...initialization ... ;

Jak zmieniamy zawartość to jest to widoczne jako jawne (explicit) podstawienie :
myList = myList.prepend(x);

  1. kolejny krok ku złu:
    finalna referencja (niezmienna) do mutowalnej klasy
    final java.util.List<String> myList = ... initialization ...;

Dlaczego to gorsze od 2?
zmianny nie są jawne (explicit) - czyli możesz wywoałać otherClass.sendMails(myList); a wredna metoda sendMail() w środku np. wywali z listy wszystkie wartości, które nie są poprawnymi emailami.

  1. najgorzej - zło wcielone (chaotyczny zły)
    ** nie dość, że zmienna to jeszcze do mutowalnej klasy** .
    Mamy dwa sposoby zmieniania wartości - chaos i masakra.
    java.util.List<String> myList = ..initialization...

Nawet jak olewamy wartości funkcyjne to jest to niepotrzebny chaos.

Uwaga:

Jak się jest początkującym w javie to wystarczy IMO nie robić sobie 4).

teez
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 122
0

Możesz @jarekr000000 dokładniej powiedzieć co jest nie tak w sposobie:

Kopiuj
private LinkedList<String> myList = new LinkedList<>();

według mnie jest to bardzo wygodne, ponieważ nie musimy się martwić o NPE. Takie wydaje mi się to najbardziej naturalne. Przecież później w konstruktorze niekoniecznie trzeba coś z taką listą robić.

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.