JavaRush /จาวาบล็อก /Random-TH /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 กับ ทรีแมป กับ แฮชเทเบิลกับ 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){}คอมไพเลอร์เองก็จะไม่เพิ่มสิ่งใดเข้าไป นี่คือสิ่งที่เราเห็นในตัวอย่างของเรา

    Constructor ของคลาสSubไม่ว่าอันไหนก็ตาม จะเรียก Constructor เริ่มต้นของคลาสSuperเนื่องจากไม่มีการระบุอย่างอื่นอีก เนื่องจากไม่มีตัวสร้างเริ่มต้นในคลาสSuperสิ่งนี้จะทำให้เกิดข้อผิดพลาดในการคอมไพล์

    วิธีแก้ปัญหาแรกสำหรับปัญหานี้คือการเพิ่มคอนสตรัคเตอร์เริ่มต้นให้กับคลาสSuper

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

    ตัวเลือกที่สองคือการลบคอนสตรัคเตอร์ที่เราอธิบายออกจากคลาสSuperเพื่อให้คอมไพเลอร์สร้างคอนสตรัคเตอร์เริ่มต้น

    และตัวเลือกสุดท้ายคือการเพิ่มการเรียกsuper(value)ตัวสร้างคลาสSubเพื่อให้ตัวสร้างคลาสที่มีอยู่ถูกเรียกแทนตัวสร้างเริ่มต้นSuper

    ตัวสร้าง Super และ 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

    หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการจัดเก็บสตริงในหน่วยความจำ โปรดอ่านสร้างสตริง Java โดยใช้ "" หรือ Constructor? .

แผนการในอนาคต. รายการนี้อิงตามการวิเคราะห์ของฉันเกี่ยวกับโครงการ Open Source จำนวนมากจาก GitHub คำถามจาก Stack Overflow และคำถามยอดนิยมบน Google ฉันไม่คิดว่าจะพิสูจน์ได้ว่าจริงๆ แล้วข้อผิดพลาดเหล่านี้เป็นหนึ่งในข้อผิดพลาดที่ร้ายแรงที่สุดสิบประการ แต่จริงๆ แล้วมันเป็นเรื่องธรรมดามาก
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION