James James - 14 days ago 4
Java Question

Why am I not catching this exception properly?

I'm trying to catch an Exception that should show an error message but doesn't seem to be doing so. I have made another block of code that is exactly the same apart from the changes of some variable names and that catches an exception but this one doesn't seem to be doing so. The purpose of the exception is that the program should look for a Plant object and if it is not found it should throw an exception to show that herbivores only eat plants. Here is the relevant pieces of code:

Main method

import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {
public Main() {
super();
}
Rabbit rabbitExample = new Rabbit();


public static void main(String[] args) {

Rabbit rabbitExample = new Rabbit();

System.out.println("************EXCEPTION 2************");

try {

Food pork = new Food("Prok");
System.out.println("************Herbivore caught Exception example************");
System.out.println("Exception caught");
rabbitExample.eat(pork);
//wolfExample.eat(vegFood);

} catch (Exception e) {
// TODO: Add catch code

e.printStackTrace();
}

try {

System.out.println("************Herbivore non-caught Exception example************");
Food vegiFood = new Plant("Vegetables"); // you create a Meat object and store it in a Food variable (so to speak)
System.out.println("Herbivores eat " + rabbitExample.eat(vegiFood)); // must be surrounded by a try-catch block
}
catch (Exception ex) {
// TODO: Add catch code
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);;

}
}
}


Animal class

abstract public class Animal
{

String name;
int age;
String noise;

abstract public void makeNoise();

public String getName() {
return name;
}

public void setName(String newName) {
name = newName;
}

abstract public Food eat(Food x) throws Exception;

}


Rabbit class

public class Rabbit extends Herbivore
{

Rabbit()
{
name = "Haryy";
age = 2;
}

public void makeNoise()
{
noise = "Squeek!";
}
public String getNoise()
{
return noise;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}

public String eat(String Food)
{
return Food;
}
public Food eat(Food x) throws Exception
{
if (x.equals(new Plant("Meat"))) {
throw new Exception("Herbivores only eat plants!");
} else {
return x;
}
}
}


Herbivore class

public class Herbivore extends Animal
{

public Food eat(Food x) throws Exception
{
if (x.equals(new Plant("Meat"))) {
throw new Exception("Herbivores only eat plants!");
} else {
return x;
}

}

public void makeNoise()
{
noise = "Woof!";
}
public String getNoise()
{
return noise;
}
}


Food class

public class Food {

//field that stores the name of the food
public String name;

//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}

public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}


I apologist about the amount of code displayed but I wanted to show all relevant code required in order to run the program. The output is as displayed:

************EXCEPTION 2************
************Herbivore caught Exception example************
Exception caught
************Herbivore non-caught Exception example************
Herbivores eat Vegetables


Whereas the output should be:

************EXCEPTION 2************
************Herbivore caught Exception example************
Exception caught
java.lang.Exception: Herbivores only eat plants!
************Herbivore non-caught Exception example************
Herbivores eat Vegetables


Any help is appreciated, thanks.

Answer

Hetre is your problem:

public Food eat(Food x) throws Exception
    {
        if (x.equals(new Plant("Meat"))) {
                throw new Exception("Herbivores only eat plants!");
            } else {
                return x;
            }    
    }

Your Food subclass does not overwrite equals() (and hashcode()). The default implementation in class Object merrily does a == compare which is always false for different objects even if they are logically the same.

But resist the temptation to implement equals() (and hashcode()) in class Food. only concrete classes (classes you create objects from) can really tell if some other object is equal.