2

I'm new here, so I'm not sure if it's ok to have 2 questions in the same post, so if I'm not supposed to just tell me (nicely!) and I'll change it to one question here and start another post elsewhere.

First problem:

Below on lines 5-8 I'm referring to two strings that I need to compare to see if they are the same. I'm using the getUserInput() method to get a response from the user at terminal and then I'm having it go ahead and print both strings so that I can visually inspect them, and they are coming up the same. However, the if section that is supposed to run when they are the same never runs and then the else section always does.

Second problem:

In the else section right below, whenever the currentChump's health is reduced to < 1, I get a block of exceptions that I've never seen before and don't know what do do about.

Here is my code, and then below I will paste the exception:

for (Chump currentChump : chumpArray) {
    System.out.println(" ");
    String playerChoice = helper.getUserInput(
                          "Type the name of the Weapon that you wish to use.");
    System.out.println(playerChoice);
    System.out.println(currentChump.getWeakness().toLowerCase());
    if (currentChump.getWeakness().toLowerCase() == playerChoice) {
        chumpArray.remove(currentChump);
    } // END IF
    else {
        while (PlayerIsAlive && currentChump.getHealth() > 0) {
            int damage = (int) Math.floor((Math.random() * 6) + 1);
            System.out.println(currentChump.getName() + " has "
                             + currentChump.getHealth() + "health remaining.");
            currentChump.setHealth(currentChump.getHealth() - damage);
            System.out.println("You hit the enemy for " 
                             + damage + " points of damage.");
            System.out.println(currentChump.getName() + " has " 
                             + currentChump.getHealth() + " health remaining.");
    System.out.println(" ");
            if (currentChump.getHealth() < 1) {
                chumpArray.remove(currentChump);
            } // END IF
            else {
                int damage2 = (int) Math.floor((Math.random() * 4) + 1);
                player.setHealth(player.getHealth() - damage2);
                if (player.getHealth() < 1) {
                    PlayerIsAlive = false;
                } // END IF
            } // END WHILE
        } // END ELSE
    } // END ELSE
} // END FOR

exception:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at ArenaGameCopy.startPlaying(ArenaGameCopy.java:87)
at ArenaGameCopy.main(ArenaGameCopy.java:168)
4

3 に答える 3

7

IteratorList からアイテムを削除し、基になるリストを変更する代わりにIterator.remove()を使用する場合は、ループに使用します。

JavaDoc の引用

...一般に、あるスレッドがコレクションを変更しているときに、別のスレッドがコレクションを反復処理することは許可されていません。一般に、反復の結果は、これらの状況では未定義です。一部の Iterator 実装 (JRE によって提供されるすべての汎用コレクション実装の実装を含む) は、この動作が検出された場合に、この例外をスローすることを選択する場合があります。これを行う反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗するため、フェイルファスト反復子として知られています。

この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示すわけではないことに注意してください。1 つのスレッドが、オブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行すると、オブジェクトはこの例外をスローする可能性があります。たとえば、フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします。

一般的に言えば、同期されていない同時変更が存在する場合に厳密な保証を行うことは不可能であるため、フェイルファストの動作は保証できないことに注意してください。フェイルファスト操作は、ベスト エフォート ベースで ConcurrentModificationException をスローします。したがって、この例外の正確性に依存するプログラムを作成するのは誤りです。ConcurrentModificationException は、バグを検出するためだけに使用する必要があります。


手伝わせてください。コード内のコメントを読んでください。

import java.util.*;

/**
  Hello! Welcome to basics.
  This is what called a SSCCE.
  Next time anyone asks for it, do it.
  Because, 90% of the times, creating SSCCE will help you identify the issue.
  Hope you learn something from these lines.

  To compile and execute this code do the following:
  a. Paste this class from import to last closed bracket in a 
     file named Test.java
  b. javac Test.java
  c. java Test
  Bliss!
*/
public class Test{

  public static void main(String[] args){
    // 1. Do not worry about these lines
    //    I am just creating some sample data
    List<String> chumpArray = Arrays.asList("Oh my god! You must know to create SSCCE".split("\\s"));
    chumpArray = new ArrayList<String>(chumpArray);
    System.out.println("List to be iterated: " + chumpArray);

    // 2. This is what I meant when I said to use an Iterator
    //    Obviously, your iterator will look like Iterator<Chump>
    for(Iterator<String> chumpIt = chumpArray.iterator(); chumpIt.hasNext();) {

        // 3. Materialize the current item
        String currentChump = chumpIt.next();
        System.out.println("Currently on: " + currentChump);

        // 3. String comparison
        //    ==            WRONG
        //    .equals       RIGHT
        if (currentChump.toLowerCase().equals("you")) {
          System.out.println("DELETING: " + currentChump);
          // 4. Just ask the iterator to remove the current Item
          chumpIt.remove();
          // Was it really so hard?!
        }
    }
    System.out.println("List after delete: " + chumpArray);
  }
}

これを実行すると、

tmp$ java Test
List to be iterated: [Oh, my, god!, You, must, know, to, create, SSCCE]
Currently on: Oh
Currently on: my
Currently on: god!
Currently on: You
DELETING: You
Currently on: must
Currently on: know
Currently on: to
Currently on: create
Currently on: SSCCE
List after delete: [Oh, my, god!, must, know, to, create, SSCCE]

HTH
ニシャント

于 2013-07-28T03:00:25.597 に答える
4

最初の問題

文字列を比較するときは、常にequalsを使用してください。

==オペレーターが行うことは、オブジェクトが同一であるかどうかを確認することです。

これが文字列で機能するように見える唯一の理由は、インターンと呼ばれるもののためです。

これは、String コンストラクターが明示的に使用されていない限り、同じ文字シーケンスを持つ参照は同じ String オブジェクトを指していることを意味します。これはおそらくメモリ使用量を減らすためです。

第二の問題

Exception in thread "main" java.util.ConcurrentModificationException

これは、強化された for ループを使用して反復している構造を変更することによって発生します。

このリンクは、例外がスローされる理由を説明しています。

イテレータの各 next() メソッド呼び出しで、

  final void checkForComodification() {
      if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
  }

メソッドが呼び出され、リストに作成された可能性があるかどうかを確認します。これは、一致しない場合に ConcurrentModificationException をスローします。

追加コメント

部分的に尊重しているように見える規則のために、ブール変数の名前を からPlayerIsAliveに変更できますisPlayerAlive。これはキャメルケースで、最初の極小数と「is」を使用して、真/偽の値であることを読者に即座に示します。

于 2013-07-28T03:35:42.950 に答える