Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

To jest post przetłumaczony przez AI.

제이온

[Efektywny Java] Punkt 6. Unikaj niepotrzebnego tworzenia obiektów

  • Język pisania: Koreański
  • Kraj referencyjny: Wszystkie kraje country-flag

Wybierz język

  • Polski
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Nederlands
  • हिन्दी
  • Magyar

Tekst podsumowany przez sztuczną inteligencję durumis

  • Tworzenie instancji String lub Boolean za pomocą słowa kluczowego new jest marnotrawstwem pamięci, dlatego zaleca się deklarowanie ich jako literałów lub użycie metody Boolean.valueOf().
  • Metoda String.matches() wykorzystuje wyrażenia regularne, co może prowadzić do problemów z wydajnością. Lepiej jest buforować instancje Pattern i ponownie ich używać.
  • W przypadku zwracania obiektów widoku, takich jak metoda keySet(), bezpieczniej jest użyć kopii obronnej, aby zwrócić nowy obiekt.

W przypadku tworzenia niepotrzebnych obiektów

Użycie new String()

String a = new String("hi");
String b = new String("hi");


Ciągi znaków a, b i c będą zawierały ten sam ciąg znaków „hi”. Jednak, ponieważ adresy, na które odwołują się te trzy ciągi znaków, są różne, występuje marnotrawstwo, ponieważ przydzielana jest oddzielna pamięć dla tych samych danych.


Untitled


Dlatego podczas deklarowania ciągów znaków, zamiast słowa kluczowego new należy użyć literału.


String a = "hi";
String b = "hi";


Powyższy kod wykorzystuje tylko jeden egzemplarz. Co więcej, użycie tej metody gwarantuje, że wszystkie kody korzystające z literału ciągu znaków „hi” w tej samej maszynie wirtualnej Java będą współdzielić ten sam obiekt. Jest tak ze względu na funkcję puli stałych w Javie.


Użycie new Boolean()

Powyższy kod tworzy instancję Boolean za pomocą konstruktora, który przyjmuje ciąg znaków jako argument. Boolean może być tylko true lub false, a tworzenie instancji za każdym razem jest marnotrawstwem pamięci. Dlatego lepiej jest użyć statycznej metody fabrycznej Boolean.valueOf().



Użycie String.matches()

Jeśli koszt tworzenia jest duży, lepiej jest je buforować i ponownie wykorzystywać, ale nie zawsze wiemy, jaki jest koszt tworzenia przez nas obiektów. Na przykład, jeśli chcesz napisać metodę sprawdzającą, czy dany ciąg znaków jest prawidłową liczbą rzymską, najłatwiej jest skorzystać z wyrażeń regularnych, jak pokazano poniżej.


public static boolean isRomanNumeral(String s) {
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");


Jednak String.matches() jest metodą, która ma problemy z wydajnością. Instancja Pattern, która jest tworzona wewnętrznie przez tę metodę dla wyrażeń regularnych, jest używana tylko raz i jest natychmiast usuwana przez kolekcjoner śmieci. Jeśli częstotliwość wykorzystywania wyrażeń regularnych jest duża, koszt tworzenia i usuwania tych samych instancji Pattern wzrasta. Dlatego lepiej jest buforować instancję Pattern z wyprzedzeniem i ponownie ją wykorzystywać przy każdym wywołaniu metody isRomanNumeral().


public class RomanNumerals {

    private static final Pattern ROMAN = Pattern.compile(
        "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    public static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }


Uwaga

We wszystkich powyższych przykładach, podczas buforowania niepotrzebnych obiektów, wszystkie obiekty zostały utworzone jako niezmienne. Jest tak dlatego, że tylko wtedy są one bezpieczne do ponownego użycia. Jednak, istnieją przypadki, które są sprzeczne z intuicją, że ponowne użycie jest możliwe tylko wtedy, gdy obiekt jest niezmienny.


Adapter (widok) to obiekt, który deleguje rzeczywistą pracę do obiektu zaplecza, a sam działa jako drugi interfejs. Adapter musi zarządzać tylko obiektem zaplecza, więc wystarczy stworzyć jeden adapter na każdy obiekt zaplecza.


Na przykład metoda keySet() interfejsu Map zwraca widok Set zawierający wszystkie klucze obiektu Map. Można by pomyśleć, że za każdym wywołaniem metody keySet() tworzona jest nowa instancja Set, ale w rzeczywistości, patrząc na implementację JDK, za każdym razem zwracana jest ta sama zmienna instancja Set.


Jest tak dlatego, że chociaż zwracana instancja Set jest zmienna, funkcje, które wykonuje, są identyczne dla wszystkich instancji Set, a wszystkie instancje Set reprezentują instancję Map. Dlatego, nawet jeśli metoda keySet() utworzy wiele obiektów widoku, nie ma powodu ani korzyści z tego.


public class UsingKeySet {

    public static void main(String[] args) {
        Map menu = new HashMap<>();
        menu.put("Burger", 8);
        menu.put("Pizza", 9);

        Set names1 = menu.keySet();
        Set names2 = menu.keySet();

        names1.remove("Burger");
        System.out.println(names1.size()); // 1
        System.out.println(names2.size()); // 1
    }


Dlatego modyfikując instancję names1, jak pokazano powyżej, wpływa to również na instancję names2.


Osobiście jednak uważam, że wartość zwracana przez metodę keySet() powinna być zawsze nowym obiektem, utworzonym za pomocą kopiowania obronnego. Jeśli instancja Set, która została odebrana z metody keySet(), jest również używana gdzie indziej i istnieje kod, który zmienia jej stan, to nie można być pewnym stanu bieżącej używanej instancji Set i instancji Map.


Ponadto, o ile środowisko nie jest nadmiernie obciążone używaniem metody keySet(), utworzenie interfejsu Set za każdym razem nie ma negatywnego wpływu na wydajność. Myślę, że lepiej jest tworzyć interfejs Set jako obiekt niezmienny, aby zapewnić stabilność i łatwość konserwacji.


Autoboxing

Autoboxing to technika, która automatycznie konwertuje typy podstawowe i typy opakowaniowe, gdy programista używa ich razem. Jednak autoboxing nie eliminuje całkowicie różnicy między typami podstawowymi i typami opakowaniowymi, a jedynie zaciera ją.


public static long sum() {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    return sum;


Logicznie rzecz biorąc, nie ma tu problemu, ale jest to kod bardzo nieefektywny pod względem wydajności. Przyczyną tego jest typ sum i typ i znajdujący się w pętli for.


Typ sum to Long, a i to long. Oznacza to, że long typu i podczas iterowania przez pętlę i dodawania do sum, tworzy nową instancję Long. W rezultacie, należy używać typów podstawowych zamiast typów opakowaniowych i zwracać uwagę na to, aby niepotrzebne autoboxingi nie były używane.


Części, których należy unikać

Nie należy mylić uniknięcia niepotrzebnego tworzenia obiektów z tym, że koszty tworzenia obiektów są wysokie, więc należy ich unikać.


Szczególnie w dzisiejszych czasach w maszynach wirtualnych Java, tworzenie i usuwanie małych obiektów, które są niepotrzebne, nie jest zbyt uciążliwe. Dlatego nie należy tworzyć własnej puli obiektów, chyba że jest to obiekt o dużym koszcie, taki jak połączenie z bazą danych.


Co więcej, należy pamiętać, że szkoda spowodowana ponownym użyciem obiektów w sytuacji, w której potrzebne jest kopiowanie obronne, jest znacznie większa niż szkoda spowodowana powtarzającym się tworzeniem obiektów. Powtarzające się tworzenie wpływa tylko na formę kodu i wydajność, ale awaria kopiowania obronnego prowadzi bezpośrednio do błędów i problemów z bezpieczeństwem.


Źródło

제이온
제이온
제이온
제이온
[Efektywny Java] Element 5. Użyj wstrzykiwania zależności zamiast jawnego zarządzania zasobami Jeśli klasa zależy od zewnętrznych zasobów, lepiej nie używać singletonów ani statycznych klas narzędzi. Wstrzykiwanie zależności może poprawić elastyczność, ponowne użycie i łatwość testowania klasy, a wzorzec fabryki metod może prowadzić do bardziej wyd

28 kwietnia 2024

[Java] Synchronized Collection vs Concurrent Collection W tym artykule porównano i przeanalizowano różne metody rozwiązywania problemów synchronizacji w środowiskach wielowątkowych w języku Java, a także ich wady i zalety. Przedstawiono cechy i różnice w wydajności między zsynchronizowanymi kolekcjami, takimi

25 kwietnia 2024

equals() vs hashCode() W języku Java `equals()` i `hashCode()` to kluczowe metody używane do porównywania równości i tożsamości obiektów. `equals()` porównuje, czy zawartość obiektów jest taka sama, podczas gdy `hashCode()` sprawdza, czy obiekty są identyczne. W strukturach dan

25 kwietnia 2024

[Javascript] Struktura obiektu (V8) Obiekt JavaScript w silniku V8 jest optymalizowany jak struktura w zależności od stanu, przełączając się między szybkim trybem i trybem słownika, który działa jako mapa skrótów. Szybki tryb jest szybki, gdy klucz i wartość są prawie stałe, ale może spowol
곽경직
곽경직
곽경직
곽경직
곽경직

18 marca 2024

Jak Rust zapobiega błędom współbieżności Rust to potężny język, który rozwiązuje wyzwania związane z programowaniem współbieżnym. Jego system typów i model własności zapewniają bezpieczeństwo podczas przekazywania i udostępniania danych między wątkami. Wzory zmienności wewnętrznej, takie jak Mut
곽경직
곽경직
곽경직
곽경직
곽경직

28 marca 2024

[Bez stopnia, przetrwać jako programista] 14. Podsumowanie często zadawanych pytań na rozmowach kwalifikacyjnych dla początkujących programistów Przewodnik po przygotowaniu do rozmów kwalifikacyjnych dla programistów. Wyjaśnia takie pojęcia często pojawiające się podczas rozmów jak: obszary pamięci głównej, struktury danych, RDBMS i NoSQL, programowanie proceduralne i obiektowe, nadpisywanie i prz
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 kwietnia 2024

[Współbieżność] Operacja atomowa: Płot pamięci i porządkowanie pamięci Ten wpis na blogu wyjaśnia, jak wziąć pod uwagę kolejność pamięci w operacjach atomowych oraz znaczenie opcji porządkowania. Zawiera szczegółowe wyjaśnienie różnych opcji porządkowania, takich jak Relaxed, Acquire, Release, AcqRel, SecCst, wraz z omówieni
곽경직
곽경직
곽경직
곽경직
곽경직

12 kwietnia 2024

Zrozumienie ryzyka inwestycji z dźwignią x3 - zanikanie zmienności (volatility decay) To wpis na blogu, w którym autor opisuje swoje zmagania z budowaniem zautomatyzowanego systemu inwestycyjnego, skupiając się na zagrożeniach związanych z inwestycjami z 3-krotnym dźwignieniem i zanikaniem zmienności. Pomimo chęci wykorzystania dźwigni do
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마

21 kwietnia 2024

[Nie mając wykształcenia, przetrwaj jako programista] 16. Wskazówki dotyczące tworzenia portfolio dla początkującego programisty Początkujący programiści (szczególnie ci bez wykształcenia) podczas tworzenia portfolio powinni jasno opisywać nie tylko technologie, ale także usługi lub funkcje, które opracowali. Na przykład w przypadku projektu „Społeczność dla osób poszukujących prac
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 kwietnia 2024