3

I'm just doing some revision for my O.O.P. Exam coming up next week and I'm stuck on a question. The question is basically give an example of bi-directional association between a Dog and a Flea. So far I've got a Dog with Fleas. The part I'm stuck on is, "Modify the dog class so that a dog object can only hold up to 5 flea objects max (print "Your dog has too many fleas!" if there's more than 5 fleas). Here's my code so far:

Dog.java

import java.util.ArrayList;

public class Dog {

    private String name;
    private int age;
    private String address;

    ArrayList<Flea> fleas = new ArrayList<Flea>(); {
        if(fleas.size() > 5) {
             System.out.println("This dog has too many fleas!");
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void hostFlea(Flea flea) {
        fleas.add(flea);
    }

    public ArrayList<Flea> getDogFlea() {
         return fleas;
    }

    public String toString() {
        return name + " the Dog (aged " + age + ") has fleas. \nThey are: " + fleas + ".";
    }   

}

Flea.java

public class Flea {

    private String name;
    private int age; 

    public Flea (String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return name + " (aged " + age + ")";
    }

}

Test.java

public class Test {

    public static void main(String[] args) {

        Dog dog = new Dog();
            dog.setName("Freddy");
            dog.setAddress("Cork");
            dog.setAge(5);

        Flea flea1 = new Flea("John", 1);
        dog.hostFlea(flea1);

        Flea flea2 = new Flea("Patrick", 3);        
        dog.hostFlea(flea2);

        Flea flea3 = new Flea("Alan", 7);
        dog.hostFlea(flea3);

        Flea flea4 = new Flea("Steven", 2);
        dog.hostFlea(flea4);

        Flea flea5 = new Flea("Charles", 5);
        dog.hostFlea(flea5);

        Flea flea6 = new Flea("Derek", 1);
        dog.hostFlea(flea6);

        Flea flea7 = new Flea("Kevin", 8);
        dog.hostFlea(flea7);

        System.out.println(dog);

    }

}

Console:

Freddy the Dog (aged 5) has fleas. They are: [John (aged 1), Patrick (aged 3), Alan (aged 7), Steven (aged 2), Charles (aged 5), Derek (aged 1), Kevin (aged 8)].

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Jaywin
  • 65
  • 3

4 Answers4

1

Add checking your condition here:

public void hostFlea(Flea flea) {
    if(fleas.size() >= 5) {
        System.out.println("This dog has too many fleas!");
    } else {
        fleas.add(flea);
    }
}

not at definition of your list variable (as you did), because you just added an instance initialization block.

Community
  • 1
  • 1
Filipp Voronov
  • 4,077
  • 5
  • 25
  • 32
  • Thanks for that, just had it in the wrong place, makes sense now! I also put in "System.exit(0);" in the IF statement so that the info doesn't appear regardless, but only if there's less than 5 fleas. Thanks again. – Jaywin Aug 16 '15 at 20:19
  • 2
    @Jaywin, `System.exit(0);` is a very bad approach, especially on exams :). If you want immediately explicitly exit from the method just call `return`. – Filipp Voronov Aug 16 '15 at 20:22
  • 1
    An alternative to just returning would be to throw an exception. A `IllegalStateException` would be a sound choice. – fabian Aug 16 '15 at 20:23
  • @fabian, yes, but in this case it would be against the task specification. – Filipp Voronov Aug 16 '15 at 20:27
  • @PhilipVoronov I tried return but it printed out the "This dog…" part multiple times. I must look at that again. – Jaywin Aug 16 '15 at 20:38
  • @Jaywin, if you want just return from `hostFlea` method if there are 5 freas without printing "This dog has too many fleas!", just substitute `System.out.println(...);` line by `return;`. – Filipp Voronov Aug 16 '15 at 20:43
1

I guess your are forced to use ArrayList. So you have to ensure no one modifies the list other as your dog class. So make the List private

private ArrayList<Flea> fleas = new ArrayList<Flea>();

Return a copy and do not expose the original List in the getDogFlea method

public ArrayList<Flea> getDogFlea() {
     return new ArrayList(fleas); //use copy constructor to not expose original list
}

And add the check in your hostFlea method.

public void hostFlea(Flea flea) {
    if(fleas.size() == 5 ) {
        System.out.println("This dog has too many fleas!");
        return; //so the 6th element is not added
    }
    fleas.add(flea);
}

Maybe last is enough for your exam but the getter would a problem in a real program ensuring there are never more as 5 elements.

mszalbach
  • 10,612
  • 1
  • 41
  • 53
  • 2
    Returning a [unmodifiable `List`](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableList-java.util.List-) instead of a new `ArrayList` would be better (although the return type needs to be modified for that). – fabian Aug 16 '15 at 20:22
  • Thanks for the detailed answer. Yea it'll be great for my exam answer but I see how it'll be problematic if a real life situation. Unfortunately I'm not sure how much more Java I'll be doing in this course so I don't think I'll have much more time to go into more/better detail. – Jaywin Aug 16 '15 at 20:25
  • No problem but for most Java exams I took and know its important to know the difference between call by reference and call by value and even its not important in this question maybe in a later one ;) – mszalbach Aug 16 '15 at 20:28
1

The public method a dog is supposed to add a flea is hostFlea, so you need to change that:

public void hostFlea(Flea flea) {
    // If the dog already has at least 5 fleas, you can't add another
    if (fleas.size() >= 5) {
        System.out.println("Your dog has too many fleas!");
    } else {
        fleas.add(flea);
    }
}

However, getDogFlea() returns the internal ArrayList, so there's nothing stopping a determined user from calling dog.getDogFlea().add(flea6). In order to protect against such behavior, you could either copy the data:

public ArrayList<Flea> getDogFlea() {
     return new ArrayList<>(fleas);
}

Or, at the "cost" of relaxing the API to return a List instead of an ArrayList, the text book solution would be to use Collections.unmodifiableList:

public List<Flea> getDogFlea() {
     return Collections.unmodifiableList(fleas);
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
0

In your hostFlea method:-

Before adding the Flea object to fleas ArrayList in Dog class, just check the size of this arraylist.

Like:-

public void hostFlea(Flea flea){
if(fleas.size() > 5) {
  System.out.println("This dog has too many fleas!");
        }
 else{
fleas.add(flea);
   }
}
Amit Bhati
  • 5,569
  • 1
  • 24
  • 45