-1

次の関数では、ローカル変数を宣言しallPeopelましたitr(グローバル変数をオーバーライドしています)。ローカル変数 (以下の Astrix の間) をコメントアウトすると、ConcurrentModificationError がスローされます。ただし、グローバル変数の代わりにローカル変数を使用すると、コードは正常に機能します。なぜそうなのか理解できませんか?クラスには他にも多くの関数があるため、より効率的なコードのためにグローバル変数を使用しようとしています。

   public void removeAPerson(){
        int id;
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter ID of person to delete > ");
        id = sc.nextInt();
        sc.nextLine();
        System.out.println();

        /*************************************/
        ArrayList<Person> allPeople;
        allPeople = Person.getAllPeople();
        Iterator itr = allPeople.iterator();
        /*************************************/

        while(itr.hasNext()){
            Person obj = (Person) itr.next();
            int ID = obj.getID2();
            if(ID == id){
                itr.remove();
                break;
            }
        }
    }
4

2 に答える 2

2

これはおそらくあなたが持っているもののスケッチです:

public class MyClass {
  List<Person> persons = new ArrayList<>();
  Iterator<Person> iter = strs.iterator();

  public void addPerson(Person p) {
    persons.add(p);
  }

  public void removePerson() {
    ... your posted code ...
  }


  public static void main(String... args) {
    MyClass c = new MyClass();
    c.addPerson(new Person());
    c.removePerson();
  }

イテレータを 1 回だけインスタンス化し、リストに何かを追加してから、イテレータを使用します。このようにイテレータのグローバル インスタンスを再利用することはまったく意味がありません。具体的には、インスタンス化した後は、反復子自体を使用する場合を除き、リストを変更してはなりません。

グローバル変数を使用することと、イテレータのグローバルインスタンスを使用することは別のことです。どちらも間違っていますが、後者は致命的です。

于 2012-11-10T13:57:30.773 に答える
0

ローカル変数を使用すると、スレッドがメソッドを呼び出すたびに、他のスレッドでは使用できないこれらの変数の新しいインスタンスが作成されます(特に参照の受け渡しを許可しない限り)。したがって、他のスレッドはオブジェクトを変更できません。

グローバル(変数、属性を意味すると思いますinstance)を使用すると、オブジェクトにアクセスできるすべてのスレッドがオブジェクトの属性にアクセスでき(直接、オブジェクトメソッドを実行して変更できます)、他のスレッドが反復を実行しています。反復されているが変更されたiteratorことをcanが検出できるため、Collectionこれが発生すると例外がスローされます(つまり、「コレクションのすべてのオブジェクトを反復していましたが、これらのオブジェクトは同じではなくなったため、これも同じです。混乱し、私は失敗します」。

于 2012-11-10T13:55:57.613 に答える