Pregunta

I have the following simple code to simulate cat hunting:

import java.util.Arrays;
import java.util.LinkedList;

public class HuntigSaeson {
    int hunger = 4;
    int level = 3;
    LinkedList<String> cats = new LinkedList<String>(Arrays.asList(
        "1.Ginger",
        "3.Porkchops",
        "2.Muffin",
        "2.Max",
        "1.Carrot",
        "2.Puffy",
        "1.Fatty"
    ));

    void hunt() {
        Integer catLevel = null;
        do {
            if (catLevel != null)
              rest();
            catLevel = new Integer(findCat().split("\\.")[0]);
            huntCat(catLevel);
            if (hunger > 5) throw new RuntimeException("x_x");
        } while (hunger > 0);
        System.out.println("^_^");
    }

    void rest() { hunger += 1; }

    String findCat() {
        hunger += 1;
        String c = cats.pop();
        System.out.println("found " + c);
        return c;
    }

    private void huntCat(int catLevel) {
        hunger += 1;
        if (catLevel < level) {
            System.out.println("chomp chomp chomp");
            hunger -= 4;
        }
    }

    public static void main(String[] args) { new HuntigSaeson().hunt(); }
}

It produces this output:

found 1.Ginger
chomp chomp chomp
found 3.Porkchops
found 2.Muffin
chomp chomp chomp
found 2.Max
chomp chomp chomp
found 1.Carrot
chomp chomp chomp
found 2.Puffy
chomp chomp chomp
found 1.Fatty
chomp chomp chomp
^_^

The intent of the null comparison line is that I don't want to rest before hunting the first cat. Netbeans highlights the line, saying I should remove it.

netbeans highlighting

So I do, by changing

            if (catLevel != null)
              rest();

to

          rest();

But now I die:

found 1.Ginger
chomp chomp chomp
found 3.Porkchops
Exception in thread "main" java.lang.RuntimeException: x_x
    at HuntigSaeson.hunt(HuntigSaeson.java:24)
    at HuntigSaeson.main(HuntigSaeson.java:46)

Why? How can I fix this?

¿Fue útil?

Solución

Why does my application break when I remove the null check?

The first thing to note is this: The Netbeans warning is wrong.

By removing the null check around rest(); you are changing the flow of the first run of your do while loop. Importantly, you are allowing rest() to be called. The net effect of this is that hunger is now larger than it normally would be had you left the null check in place.

What's now happening is this:

  • First loop iteration begins: hunger = 4, level = 3
  • rest() is called: hunger increments to 5.
  • findCat() is called: hunger increments to 6, "1.Ginger" is returned.
  • huntCat(1) is called: hunger increments to 7.
  • 1 < 3 (catLevel < level) evaluates to true, causing hunger to be decremented by 4 (so we're now at 3).
  • hunger is not greater than 5, so continue to the next iteration.
  • Second loop iteration begins: hunger = 3, level = 3
  • rest() is called, hunger increments to 4.
  • findCat() is called, hunger increments to 5, "3.Porkchops" is returned.
  • huntCat(3) is called, hunger increments to 6
  • 3 < 3 (catLevel < level) evaluates to false, hunger does not get decremented.
  • hunger is greater than 5, so RuntimeException("x_x") is thrown.

How can I fix this?

Well, given that the Netbeans warning is wrong (because catLevel definitely is null in the first iteration), the simplest solution is just to reinstate your null check and ignore the warning.

If you wish, you can disable the warning by clicking the lightbulb next to the warning on the left side, browsing the menus, and choosing "Disable warning". Though personally I would rather put up with one aggravating yellow underline if it lead to better quality code in the long run.

Alternatively, increase level to 4, or decrease hunger to 3, or change your if statement to check if hunger > 6 instead.

Otros consejos

For what it's worth, I did not see that warning when I tried your code with:

Product Version: NetBeans IDE 8.0 (Build 201403101706)
Java: 1.8.0; Java HotSpot(TM) 64-Bit Server VM 25.0-b70
Runtime: Java(TM) SE Runtime Environment 1.8.0-b132
System: Windows 8 version 6.2 running on amd64; Cp1252; en_US (nb)

So I suspect it was a false-positive warning in NetBeans that has since been fixed.

That said, you can achieve the same output without the null check by changing the initial value of hunger to 3, e.g.

public class HuntigSaeson {
    int hunger = 3;

    ...
    void hunt() {
        Integer catLevel;
        do {
            rest();
            catLevel = new Integer(findCat().split("\\.")[0]);
            huntCat(catLevel);
            if (hunger > 5) throw new RuntimeException("x_x");
        } while (hunger > 0);
        System.out.println("^_^");
    }
    ...
}

As a simple answer : the Netbeans warning is wrong. Netbeans says the expression is never null, although it is null in first iteration. Simply ignore the Warning. Not all warnings are intended to be treated. That's why they are configurable in Netbeans itself to be off/on.

I don't recommend to disable it as :

  • It should have been resolved now with earlier versions of Netbeans.

  • It will not disable other real "never null expressions"

Try the following:

    void hunt() {
    try {
        while (hunger > 0) {
            huntCat(new Integer(findCat().split("\\.")[0]));
            if (hunger > 5)
                throw new RuntimeException("x_x");
            rest();
        }
    } catch (NoSuchElementException e) {
    }
    System.out.println("^_^");
}

Error message NetBeans is reporting is actually reverse of what its intended for :)

Your if condition will always be null, so rest() will never be executed and hence hunger will stay at 4.

However when you remove the if condition reset() is called and the hunger value increments to 5 and so later on your code crashes as you just throw the exception if it's value is greater than 5 which will now be more than 5 due to calls to other methods in lines above.

What NetBeans is saying could be wrong (expression is never null), it should say (expression is always null) instead.

Fix the code logic ..

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top