JavaRush /وبلاگ جاوا /Random-FA /10 اشتباهی که اغلب توسط توسعه دهندگان جاوا انجام می شود
theGrass
مرحله
Саратов

10 اشتباهی که اغلب توسط توسعه دهندگان جاوا انجام می شود

در گروه منتشر شد
10 اشتباه اغلب توسط توسعه دهندگان جاوا - 1
این لیست شامل 10 اشتباه است که توسعه دهندگان جاوا اغلب مرتکب می شوند.
  1. تبدیل یک آرایه به ArrayList .

    برای تبدیل یک آرایه به ArrayList ، توسعه دهندگان اغلب از این روش استفاده می کنند:

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

    Arrays.asList()یک شی کلاس را برمی گرداند کهArrayList یک کلاس استاتیک خصوصی داخلی کلاس (private static class)است ، Arraysو این یک کلاس نیست . برای ایجاد یک واقعی ، این کار را انجام دهید:java.util.ArrayList.java.util.Arrays.ArrayListset()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().

    در یک Loop-style for-each، کامپایلر متد را فراخوانی می‌کند remove()و تنها پس از آن next()، یک خطا ایجاد می‌کند ConcurrentModificationException. می توانید به کد نگاه کنید ArrayList.iterator().

  4. Hashtableدر برابر HashMap.

    با توجه به پیاده سازی مربوطه، Hashtable نام ساختار داده است.

    اما در جاوا نام ساختار داده است HashMap. یکی از تفاوت های کلیدی بین Hashtableو همگام بودن HashMapآن است Hashtableبنابراین نباید Hashtableدر جایی استفاده شود HashMap.

    HashMap در مقابل نقشه درختی در مقابل 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 اشتباه اغلب توسط توسعه دهندگان جاوا - 2

    این خطای کامپایل به دلیل این واقعیت است که کلاس ancestor سازنده پیش فرض تعریف شده ندارد. در جاوا ، مگر اینکه خودتان سازنده کلاس را مشخص کنید، کامپایلر سازنده پیش فرضی ایجاد می کند که به آرگومان نیاز ندارد. اگر سازنده در کلاس Superبه صورت توضیح داده شود Super(String s){}، خود کامپایلر چیزی اضافه نخواهد کرد. این چیزی است که در مثال خود می بینیم.

    سازنده کلاس Sub، مهم نیست که کدام یک، سازنده پیش فرض کلاس را فراخوانی می کند Super، زیرا چیز دیگری مشخص نشده است. از آنجایی که هیچ سازنده پیش فرضی در کلاس وجود ندارد Super، این منجر به یک خطای کامپایل می شود.

    اولین راه حل برای این مشکل اضافه کردن یک سازنده پیش فرض به کلاس استSuper

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

    گزینه دوم این است که سازنده ای را که توضیح دادیم از کلاس حذف کنیم Superتا کامپایلر یک سازنده پیش فرض ایجاد کند.

    و آخرین گزینه این است که یک فراخوانی super(value)به سازنده های کلاس اضافه کنید Subتا سازنده کلاس موجود به جای سازنده پیش فرض فراخوانی شود.Super

    سازنده Super and Sub

  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

    برای کسب اطلاعات بیشتر در مورد نحوه ذخیره رشته ها در حافظه، ایجاد رشته جاوا با استفاده از "" یا سازنده را بخوانید؟ .

برنامه های آینده. این لیست بر اساس تجزیه و تحلیل من از تعداد زیادی پروژه منبع باز از GitHub، سؤالات Stack Overflow و سؤالات محبوب در Google است. فکر نمی کنم ثابت کنم که آنها واقعاً جزو ده اشتباه جدی هستند، اما در واقع بسیار رایج هستند.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION