JavaRush /Blog Java /Random-PL /10 błędów często popełnianych przez programistów Java
theGrass
Poziom 24
Саратов

10 błędów często popełnianych przez programistów Java

Opublikowano w grupie Random-PL
10 błędów często popełnianych przez programistów Java - 1
Ta lista zawiera 10 błędów, które często popełniają programiści Java .
  1. Konwersja tablicy na ArrayList .

    Aby przekonwertować tablicę na ArrayList , programiści często używają tej metody:

    List<String> list = Arrays.asList(arr);

    Arrays.asList()zwróci obiekt klasy , ArrayListktóry jest wewnętrzną, prywatną klasą statyczną (private static class)klasy Arraysi nie jest to klasa. java.util.ArrayList.Klasa java.util.Arrays.ArrayListzawiera metody set(),,,, ale nie zawiera żadnych metod dodawania elementów, jej rozmiar jest stały . Aby stworzyć prawdziwy , wykonaj następujące czynności:get()contains()java.util.ArrayList

    ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));

    Konstruktor klasy java.util.ArrayListmoże przyjąć jako parametr wszystkie obiekty implementujące interfejs Collection, którego implementacja jest dziedziczona przez klasęjava.util.Arrays.ArrayList

    (prywatna klasa statyczna ArrayList<E> rozszerza AbstractList<E> implementuje RandomAccess, java.io.Serializable).

  2. Sprawdzanie tablicy pod kątem określonej wartości.

    Programiści często to robią:

    Set<String> set = new HashSet<String>(Arrays.asList(arr));
    return set.contains(targetValue);

    Kod działa, ale nie ma potrzeby konwertowania go Listdo formatu Set. Konwersja na Setzajmie więcej czasu. W rzeczywistości wszystko jest proste:

    Arrays.asList(arr).contains(targetValue);

    Lub

    for(String s: arr){
    	if(s.equals(targetValue))
    		return true;
    }
    return false;

    Pierwsza metoda jest znacznie krótsza.

  3. Usuwanie elementu z Listpętli

    Rozważ następujący kod, który usuwa elementy w pętli:

    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
    for (int i = 0; i < list.size(); i++) {
    	list.remove(i);
    }
    System.out.println(list);

    Wniosek:

    [b, d]

    Okazuje się to poważnym błędem. Po usunięciu elementu jego rozmiar Listulega zmniejszeniu, a indeksy elementu ulegają zmianie.

    Unikaj więc tej metody, jeśli chcesz usunąć wiele elementów z pętli za pomocą indeksu.

    Być może wiesz, że użycie iteratora jest właściwym rozwiązaniem do usuwania elementów w pętli i wiesz, że pętla stylu for-eachdziała jak iterator, ale tak nie jest.

    Rozważ następujący kod:

    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
    
    for (String s : list) {
    	if (s.equals("a"))
    		list.remove(s);
    }

    Otrzymamy wyjątek ConcurrentModificationException .

    Właściwą rzeczą do zrobienia jest:

    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
    Iterator<String> iter = list.iterator();
    while (iter.hasNext()) {
    	String s = iter.next();
    
    	if (s.equals("a")) {
    		iter.remove();
    	}
    }

    Metodę next()należy wywołać przed metodą remove().

    W pętli for-eachkompilator wywoła metodę remove()i dopiero wtedy next(), co zgłosi błąd ConcurrentModificationException. Możesz spojrzeć na kod ArrayList.iterator().

  4. Hashtableprzeciwko HashMap.

    Ze względu na odpowiednią implementację Hashtable jest nazwą struktury danych.

    Ale w Javie nazwa struktury danych to HashMap. Jedną z kluczowych różnic między Hashtablei HashMapjest to, że jest Hashtablezsynchronizowany, dlatego nie należy go używać Hashtabletam, gdzie HashMap.

    HashMap vs. Mapa Drzewa vs. Hashtable vs. PołączonaHashMapa .

    10 podstawowych pytań na temat interfejsu Mapy

  5. Korzystaj ze zbiorów bez ograniczeń dotyczących zawartości

    В Java часто путают коллекции без ограничений по содержимому, и коллекции с маской по типу содержимого. К примеру, для множеств - Set это коллекция без ограничений по содержимому, а Set<?> — коллекция у которой все-таки есть ограничения, но эти ограничения ничего на самом деле не ограничивают. Рассмотрим следующий kod, где List без ограничений используется в качестве параметра метода:

    public static void add(List list, Object o){
    	list.add(o);
    }
    public static void main(String[] args){
    	List<String> list = new ArrayList<String>();
    	add(list, 10);
    	String s = list.get(0);
    }

    Данный kod выбросит исключение:

    Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    	at …

    Использование коллекций без ограничений по содержимому очень опасно, потому что вы не можете быть уверенными в том что там лежит внутри. А для того чтобы понять всю глубину разницы между Set, Set<?> и Set<Object> — почитайте вот эту и эту ссылки.

  6. Уровень доступа

    Очень часто для полей класса разработчики используют модификатор доступа public. Так проще получить oznaczający поля напрямую. Правильнее использовать Jak можно более ограниченный доступ к членам класса.

    public, default, protected, and private.

  7. ArrayList против LinkedList

    Когда разработчики не знают чем отличается ArrayList от LinkedList, они используют первый в силу его большей известности. Однако, есть огромная разница в производительности между ними. На самом деле, выбор между ними должен быть продиктован их внутренними особенностями — ArrayList позволяет быстро производить доступ к произвольному элементу массива, а LinkedList — быстро добавлять/удалять элементы в массиве. Почитайте статью по ссылке ArrayList vs. LinkedList чтобы понять причины их разной производительности.

  8. Mutable (Изменяемый) против Immutable (Неизменяемый)

    Неизменяемый obiekt имеет много преимуществ: простота, безопасность и т.д. Но он требует отдельного obiektа для каждого нового значения, и за слишком большое количество obiektов придется заплатить понижением производительности. Должен быть баланс при выборе между изменяемым и неизменяемым обьектом.

    В основном чтобы избежать подготовки промежуточных obiektов используется изменяемый obiekt. Один из классических примеров это конкатенация большого количества строк. Если вы используете неизменяемый obiekt типа String, то вы создаете много obiektов, которые сразу попадут в сборщик мусора. Это тратит время и энергию процессора, поэтому правильное решение это использование изменяемых обьектов (например StringBuilder).

    String result="";
    for(String s: arr){
    	result = result + s;
    }

    Еще один пример использования изменяемых obiektов — передача такого obiektа в метод. Это позволит вернуть результат в нем же, без создания лишних obiektов. При работе с obiektами большого размера, к примеру коллекциями, передача коллекции в метод для сортировки и возвращение результата в другой коллекции приводит к совершенно излишнему расходу ресурсов. (Ответ пользователя dasblinkenlight на Stack Overflow).

    Почему obiekt класса String неизменяем?

  9. Конструкторы классов Super и Sub

    10 błędów często popełnianych przez programistów Java - 2

    Ten błąd kompilacji jest spowodowany faktem, że klasa przodka nie ma zdefiniowanego konstruktora domyślnego. W Javie , jeśli sam nie określisz konstruktora klasy, kompilator utworzy domyślny konstruktor, który nie wymaga żadnych argumentów. Jeśli konstruktor jest opisany w klasie Superjako Super(String s){}, sam kompilator nic nie doda. To właśnie widzimy na naszym przykładzie.

    Konstruktor klasy Sub, nieważne który, wywoła domyślny konstruktor klasy Super, ponieważ nie określono nic innego. Ponieważ w klasie nie ma domyślnego konstruktora Super, spowoduje to błąd kompilacji.

    Pierwszym rozwiązaniem tego problemu jest dodanie domyślnego konstruktora do klasySuper

    public Super(){
        System.out.println("Super");
    }

    Drugą opcją jest usunięcie opisanego przez nas konstruktora z klasy, Superdzięki czemu kompilator utworzy konstruktor domyślny.

    Ostatnią opcją jest dodanie wywołania super(value)konstruktorów klas, Subdzięki czemu zamiast konstruktora domyślnego zostanie wywołany istniejący konstruktor klasySuper

    Konstruktor Super i Sub

  10. " " czy konstruktor?

    Istnieją dwa sposoby tworzenia ciągu znaków:

    //1. использовать двойные кавычки
    String x = "abc";

    //2. использовать конструктор
    String y = new String("abc");

    Jaka jest różnica między nimi?

    Można to zrozumieć na podstawie następujących przykładów:

    String a = "abcd";
    String b = "abcd";
    System.out.println(a == b);  // True
    System.out.println(a.equals(b)); // True
    
    String c = new String("abcd");
    String d = new String("abcd");
    System.out.println(c == d);  // False
    System.out.println(c.equals(d)); // True

    Aby dowiedzieć się więcej o przechowywaniu ciągów w pamięci, przeczytaj artykuł Tworzenie ciągu Java przy użyciu „” lub konstruktora? .

Przyszłe plany. Ta lista powstała na podstawie mojej analizy ogromnej liczby projektów Open Source z GitHub, pytań ze Stack Overflow i popularnych zapytań w Google. Nie ośmielę się udowadniać, że rzeczywiście należą one do dziesięciu najpoważniejszych błędów, ale w rzeczywistości są bardzo powszechne.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION