JavaRush /בלוג Java /Random-HE /10 טעויות שנעשות לעתים קרובות על ידי מפתחי Java
theGrass
רָמָה
Саратов

10 טעויות שנעשות לעתים קרובות על ידי מפתחי Java

פורסם בקבוצה
10 טעויות שעושים לעתים קרובות על ידי מפתחי Java - 1
רשימה זו כוללת 10 טעויות שמפתחי Java עושים לעתים קרובות.
  1. המרת מערך ל- ArrayList .

    כדי להמיר מערך ל- ArrayList , מפתחים משתמשים לעתים קרובות בשיטה זו:

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

    Arrays.asList()יחזיר אובייקט מחלקה ArrayListשהוא מחלקה סטטית פרטית פנימית (private static class)של המחלקה Arrays, וזו לא מחלקה java.util.ArrayList.המחלקה java.util.Arrays.ArrayListמכילה מתודות set(), get(), contains(), אך אינה מכילה מתודות להוספת אלמנטים, הגודל שלה קבוע . כדי ליצור אחד אמיתי java.util.ArrayList, עשה זאת:

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

    בנאי מחלקה java.util.ArrayListיכול לקחת כפרמטר את כל האובייקטים שמיישמים ממשק Collection, שהמימוש שלו עובר בירושה למחלקהjava.util.Arrays.ArrayList

    (מחלקה סטטית פרטית ArrayList<E> מרחיבה את AbstractList<E> מיישמת RandomAccess, java.io.Serializable).

  2. בדיקת מערך עבור ערך מסוים.

    לעתים קרובות מפתחים עושים זאת:

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

    הקוד עובד, אבל אין צורך להמיר אותו Listל Set. ההמרה אל Setתיקח זמן נוסף. למעשה, הכל פשוט:

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

    אוֹ

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

    השיטה הראשונה היא הרבה יותר קצרה.

  3. הסרת אלמנט מתוך Listלולאה

    שקול את הקוד הבא שמסיר אלמנטים בלולאה:

    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);

    סיכום:

    [b, d]

    מסתבר שזו טעות חמורה. כאשר אלמנט מוסר, הגודל Listמצטמצם ומדדי האלמנטים משתנים.

    אז הימנע משיטה זו אם אתה רוצה להסיר מספר אלמנטים בלולאה באמצעות אינדקס.

    אתה אולי יודע ששימוש באיטרטור הוא הפתרון הנכון להסרת אלמנטים בלולאה, ואתה יודע שלולאת סגנון for-eachעובדת כמו איטרטור, אבל זה לא.

    שקול את הקוד הבא:

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

    נקבל ConcurrentModificationException .

    הדבר הנכון לעשות הוא:

    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();
    	}
    }

    next()יש לקרוא לשיטה לפני ה- remove().

    בסגנון לולאה for-each, המהדר יקרא למתודה remove(), ורק אז next(), מה שיעלה שגיאה ConcurrentModificationException. אתה יכול להסתכל על הקוד ArrayList.iterator().

  4. Hashtableמול HashMap.

    בשל היישום המקביל, Hashtable הוא השם של מבנה הנתונים.

    אבל ב- Java השם של מבנה נתונים הוא HashMap. אחד ההבדלים העיקריים בין Hashtableלבין HashMapהוא שהוא Hashtableמסונכרן. אז אין להשתמש בו Hashtableאיפה HashMap.

    HashMap לעומת TreeMap לעומת Hashtable לעומת LinkedHashMap .

    10 שאלות בסיסיות על ממשק המפה

  5. השתמש באוספים ללא הגבלות תוכן

    В Java часто путают коллекции без ограничений по содержимому, и коллекции с маской по типу содержимого. К примеру, для множеств - Set это коллекция без ограничений по содержимому, а Set<?> — коллекция у которой все-таки есть ограничения, но эти ограничения ничего на самом деле не ограничивают. Рассмотрим следующий code, где 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);
    }

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

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

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

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

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

    public, default, protected, and private.

  7. ArrayList против LinkedList

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

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

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

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

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

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

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

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

    10 טעויות שנעשו לעתים קרובות על ידי מפתחי Java - 2

    שגיאת קומפילציה זו נגרמת מהעובדה שלמחלקת הקדמונים אין בנאי ברירת מחדל מוגדר. ב- Java , אלא אם כן תציין בנאי מחלקה בעצמך, המהדר יצור בנאי ברירת מחדל שלא דורש ארגומנטים. אם הבנאי מתואר במחלקה Superכ- Super(String s){}, המהדר עצמו לא יוסיף דבר. זה מה שאנחנו רואים בדוגמה שלנו.

    הבנאי של המחלקה Sub, לא משנה איזה מהם, יקרא לבנאי ברירת המחדל של המחלקה Super, מכיוון ששום דבר אחר לא מצוין. מכיוון שאין בנאי ברירת מחדל במחלקה Super, זה יוביל לשגיאת קומפילציה.

    הפתרון הראשון לבעיה זו הוא הוספת בנאי ברירת מחדל למחלקהSuper

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

    האפשרות השנייה היא להסיר את הבנאי שתיארנו מהמחלקה Superכך שהקומפיילר יוצר בנאי ברירת מחדל.

    והאפשרות האחרונה היא להוסיף קריאה super(value)לבוני המחלקות Subכך שבנאי המחלקה הקיים ייקרא במקום בנאי ברירת המחדלSuper

    בונה של סופר וסאב

  10. " " או קונסטרוקטור?

    ישנן שתי דרכים ליצור מחרוזת:

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

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

    מה ההבדל ביניהם?

    אתה יכול להבין זאת מהדוגמאות הבאות:

    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

    כדי ללמוד עוד על האופן שבו מחרוזות מאוחסנות בזיכרון, קרא צור Java String באמצעות "" או Constructor? .

תוכניות עתידיות. רשימה זו מבוססת על הניתוח שלי של מספר עצום של פרויקטים בקוד פתוח מ-GitHub, שאלות מ-Stack Overflow ושאילתות פופולריות ב-Google. אני לא מתיימר להוכיח שהן באמת בין עשר הטעויות החמורות ביותר, אבל הן למעשה נפוצות מאוד.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION