Java List.add () UnsupportedOperationException


225

ฉันพยายามที่จะเพิ่มวัตถุกับList<String>อินสแตนซ์ UnsupportedOperationExceptionแต่มันพ่น ไม่มีใครรู้ว่าทำไม

รหัส Java ของฉัน:

String[] membersArray = request.getParameterValues('members');
List<String> membersList = Arrays.asList(membersArray);

for (String member : membersList) {
    Person person = Dao.findByName(member);
    List<String> seeAlso;
    seeAlso = person.getSeeAlso();
    if (!seeAlso.contains(groupDn)){
        seeAlso.add(groupDn);
        person.setSeeAlso(seeAlso);
    }
}

ข้อความแสดงข้อผิดพลาด:

java.lang.UnsupportedOperationException
    java.util.AbstractList.add (ไม่ทราบแหล่งที่มา)
    java.util.AbstractList.add (ไม่ทราบแหล่งที่มา)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:722)

คำตอบ:


458

ไม่ใช่ว่าทุกคนListดำเนินการสนับสนุนadd()วิธีการ

ตัวอย่างทั่วไปหนึ่งตัวอย่างคือการListส่งคืนโดยArrays.asList(): มีการบันทึกไว้ว่าไม่สนับสนุนการเปลี่ยนแปลงโครงสร้างใด ๆ (เช่นลบหรือเพิ่มองค์ประกอบ) (เหมืองของการเน้น):

ส่งคืนรายการขนาดคงที่ซึ่งสนับสนุนโดยอาร์เรย์ที่ระบุ

แม้ว่านั่นไม่ใช่เฉพาะที่Listคุณพยายามแก้ไขคำตอบยังคงใช้กับListการใช้งานอื่น ๆที่ไม่เปลี่ยนรูปหรืออนุญาตการเปลี่ยนแปลงที่เลือกเท่านั้น

คุณสามารถหาข้อมูลเกี่ยวกับสิ่งนี้ได้โดยการอ่านเอกสารประกอบUnsupportedOperationExceptionและList.add()เอกสารฉบับนี้ให้เป็น "(การดำเนินการเพิ่มเติม)" ความหมายที่ชัดเจนของวลีนี้อธิบายไว้ที่ด้านบนของListเอกสาร

ในฐานะที่เป็นวิธีแก้ปัญหาคุณสามารถสร้างสำเนาของรายการเพื่อการใช้งานที่รู้จักปรับเปลี่ยนได้เช่นArrayList:

seeAlso = new ArrayList<>(seeAlso);

1
ดังนั้นฉันจะต้องใช้อินสแตนซ์รายการเพื่อทดสอบว่ามันมีองค์ประกอบของฉันและอินสแตนซ์อาร์เรย์เมื่อฉันต้องเพิ่มองค์ประกอบ? ที่เขียน?
FAjir

90
@Florito: สิ่งนี้จะทำงานได้: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
mre

หรือฉันอาจจะต้องโยนวัตถุรายการของฉันไปที่ ArrayList หรืออื่น ๆ ?
FAjir

2
ไม่ไม่ได้จริงๆ หากคุณต้องการเพิ่มองค์ประกอบให้กับการListใช้งานที่ไม่อนุญาตให้มีการเพิ่มคุณจะต้องคัดลอกListองค์ประกอบนั้นไปยังการใช้งานที่ทำ ( ArrayListเป็นตัวเลือกทั่วไป) และเพิ่มเข้าไป
Joachim Sauer

8

การใช้งาน List จำนวนมากสนับสนุนการสนับสนุนที่ จำกัด ในการเพิ่ม / ลบและ Arrays.asList (membersArray) เป็นหนึ่งในนั้น คุณต้องแทรกบันทึกใน java.util.ArrayList หรือใช้วิธีการด้านล่างเพื่อแปลงเป็น ArrayList

ด้วยการเปลี่ยนแปลงเล็กน้อยในรหัสของคุณคุณสามารถทำด้านล่างเพื่อแปลงรายการเป็น ArrayList ทางออกแรกคือการเปลี่ยนแปลงขั้นต่ำในโซลูชันของคุณ แต่โซลูชันที่สองได้รับการปรับให้เหมาะสมยิ่งขึ้นฉันเดา

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = new ArrayList<>(Arrays.asList(membersArray));

หรือ

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));

4

สร้างแนวคิดการสืบทอดหากบางวิธี perticular ไม่พร้อมใช้งานในคลาสปัจจุบันจะค้นหาเมธอดนั้นในคลาสสุด หากมีให้ดำเนินการ

มันรันAbstractList<E>ระดับวิธีการพ่นadd()UnsupportedOperationException


เมื่อคุณแปลงจาก Array เป็น Collection Obejct เช่น array-based ไปยัง API ที่ใช้การรวบรวมแล้วมันจะให้วัตถุการรวบรวมขนาดคงที่เนื่องจากพฤติกรรมของ Array มีขนาดคงที่

java.util.Arrays.asList (T ... a)

ตัวอย่าง Souce สำหรับโครงสร้าง

public class Arrays {
    public static <T> List<T> asList(T... a) {
        return new java.util.Arrays.ArrayList.ArrayList<>(a); // Arrays Inner Class ArrayList
    }
    //...
    private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
        //...
    }
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        //...
    }

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }
    private class ListItr extends Itr implements ListIterator<E> {
        //...
    }
}

รูปแบบดังกล่าวข้างต้นมาคุณอาจสังเกตได้ว่าชั้นไม่ได้java.util.Arrays.ArrayList @Override add(index, element), set(index, element), remove(index)ดังนั้นจากการถ่ายทอดทางพันธุกรรมจะรันซูเปอร์AbstractList<E>ระดับฟังก์ชั่นที่พ่นadd()UnsupportedOperationException

ในฐานะที่เป็นระดับนามธรรมก็มีการดำเนินการเพื่อAbstractList<E> iterator() and listIterator()เพื่อให้เราสามารถวนซ้ำวัตถุรายการ

List<String> list_of_Arrays = Arrays.asList(new String[] { "a", "b" ,"c"});

try {
    list_of_Arrays.add("Yashwanth.M");
} catch(java.lang.UnsupportedOperationException e) {
    System.out.println("List Interface executes AbstractList add() fucntion which throws UnsupportedOperationException.");
}
System.out.println("Arrays → List : " + list_of_Arrays);

Iterator<String> iterator = list_of_Arrays.iterator();
while (iterator.hasNext()) System.out.println("Iteration : " + iterator.next() );

ListIterator<String> listIterator = list_of_Arrays.listIterator();
while (listIterator.hasNext())    System.out.println("Forward  iteration : " + listIterator.next() );
while(listIterator.hasPrevious()) System.out.println("Backward iteration : " + listIterator.previous());

คุณสามารถสร้างคลาสคอลเลคชั่นอาร์เรย์ขนาดคงที่ได้ Collections.unmodifiableList(list);

ตัวอย่างแหล่งที่มา:

public class Collections {
    public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
    }
}

Collection - บางครั้งเรียกว่าภาชนะบรรจุ - เป็นเพียงวัตถุที่จัดกลุ่มองค์ประกอบหลายเป็นหน่วยเดียว คอลเลกชันที่ใช้ในการจัดเก็บเรียกจัดการและสื่อสารข้อมูลรวม

@ดูสิ่งนี้ด้วย


3

คุณต้องเริ่มต้นรายการของคุณดูนอกจากนี้:

List<String> seeAlso = new Vector<String>();

หรือ

List<String> seeAlso = new ArrayList<String>();

2
ตัวแปรเตรียมจะไม่ทำให้เกิดในUnsupportedOperationException add()คุณจะได้รับ NPE แทน
สตีเฟนซี

0

รายชื่อ membersList = Arrays.asList (membersArray);

ส่งคืนรายการที่ไม่เปลี่ยนแปลงสิ่งที่คุณต้องทำคือ

ใหม่ ArrayList <> (Arrays.asList (membersArray)); เพื่อทำให้ไม่แน่นอน


มันไม่ได้เป็นรายการที่ไม่เปลี่ยนรูป การดำเนินการกลายพันธุ์ที่ไม่เปลี่ยนความยาวของรายการได้รับการสนับสนุน / จะใช้งานได้ สิ่งสำคัญคือความยาวของรายการไม่สามารถเปลี่ยนแปลงได้เนื่องจากรายการได้รับการสำรองข้อมูลโดยอาร์เรย์ ... ซึ่งความยาวไม่สามารถเปลี่ยนแปลงได้
สตีเฟ่นซี

-1

แทนการใช้ add () เราสามารถใช้ addall ()

{ seeAlso.addall(groupDn); }

เพิ่มเพิ่มรายการเดียวในขณะที่ addAll เพิ่มแต่ละรายการจากคอลเล็กชันทีละรายการ ในท้ายที่สุดทั้งสองวิธีจะคืนค่าจริงหากมีการปรับเปลี่ยนคอลเล็กชัน ในกรณีของ ArrayList สิ่งนี้เป็นเรื่องเล็กน้อยเพราะคอลเลกชันจะถูกปรับเปลี่ยนเสมอ แต่คอลเลกชันอื่น ๆ เช่นชุดอาจส่งคืนค่าเท็จหากรายการที่ถูกเพิ่มมีอยู่แล้ว


-3

คุณไม่สามารถแก้ไขผลลัพธ์จากแบบสอบถาม LDAP ปัญหาของคุณอยู่ในบรรทัดนี้:

seeAlso.add(groupDn);

รายการ SeeAlso ไม่สามารถแก้ไขได้


1
ปัญหาไม่ได้เกิดจากสิ่งนั้น แต่อย่างที่โจอาคิมชี้ให้เห็นข้างต้นนั้นคือการใช้งานรายการซึ่งอาจไม่รองรับการเพิ่ม ()
Liv
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.