I have two questions:
- What is causing this error ?
- Am I using the service class the right way ?
I have this Person class:
public class Personne {
private int code;
private String nom;
private String prenom;
private final IPerson personService;
// with a red sign, IJ is telling me to add constructor parameter which I'm not sure why it's a "forced" thing to do
public Personne(int Code, String Nom, String Prenom){
code = Code;
nom = Nom;
prenom = Prenom;
}
public Personne(IPerson personService) {
this.personService = personService;
}
// getter, setter and toString() methods
}
Then, I have this interface which is implemented by a service class:
public interface IPerson {
void save( Personne p );
void delete( int code );
boolean update( Personne p );
Personne findById( int code );
List<Personne> findAll();
}
public class PersonneService implements IPerson{
protected ArrayList<Personne> list = new ArrayList<>();
@Override
public void save(Personne p) {
list.add(p);
}
@Override
public void delete(int code) {
list.remove(code);
}
@Override
public boolean update(Personne p) {
return list.contains(p);
}
@Override
public Personne findById(int code) {
return list.get(code);
}
@Override
public List<Personne> findAll() {
return list;
}
}
I'm doing tests on some other class:
public class PersonneTest {
public static void main(String[] args){
ArrayList<Personne> personnes = new ArrayList<>();
IPerson service = new PersonneService();
Personne p1 = new Personne(1, "Zarhloul", "Yasser");
Personne p2 = new Personne(2, "Talbi" , "Abdellah");
Personne p3 = new Personne(3, "Qabil", "Reda");
Personne p4 = new Personne(4, "Chliyah","Mohamed");
Personne p5 = new Personne(5,"Lemrabet", "Salim");
service.save(p1);
service.save(p2);
service.save(p3);
service.save(p4);
service.save(p5);
System.out.println(service.findAll());
service.delete(1);
service.update(p3);
service.findById(3);
System.out.println(service.findAll());
}
}
Full error message:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 0 at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64) at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70) at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266) at java.base/java.util.Objects.checkIndex(Objects.java:359) at java.base/java.util.ArrayList.remove(ArrayList.java:504) at ***.PersonneService.delete(PersonneService.java:16) at ***.PersonneTest.main(PersonneTest.java:24)
CodePudding user response:
1. What is causing this error ?
This is happening because this variable might not be initialized once the Personne object is instanciated, meaning that once you use the first constructor, this variable won't have any value assigned to it.
Final fields need to be assigned to exactly once. That's the java way of declaring constant values if you know other programming languages that use the concept of contants.
So you need to initialize the final variables once you declare them, for example, if you really want this variable to be final you could use something like:
private final IPerson personService = new PersonneService();
Or you should have it on all of the class constructors, not only in the second one.
2. Am I using the service class the right way ?
Yes, you are, but relating to the first question, you won't need a service object on you personne class, because it is the service wich performs actions on the personne object, not the other way around, that's the purpose of service classes.
And you are facing the error because you are trying to access a index that your list don't actually have. Like this you would've been able to access it:
System.out.println(personnes);
// this prints fine
IPerson service = new PersonneService();
// first you to fill the list somehow
personnes.forEach(personne -> service.save(personne));
System.out.println(service.findAll());
service.delete(1);
service.update(p3);
// your list have indexes 0, 1, 2 and 3, trying to access index 4 is out of bound of the list indexes
service.findById(3);
service.findAll();
System.out.println(personnes);
// this throws an error
So the index 3 is accessible, the index 4 is not.
EDIT
I added a method on your interface so we can display the elements inside the list.
PersonneService.java
@Override
public void displayPersonnes() {
list.forEach((personne -> {
System.out.println(personne "with index " list.indexOf(personne));
}));
}
PersonneTest.java
...
System.out.println(personnes);
// this prints fine
IPerson service = new PersonneService();
// filling the list with each personne of the personnes list
personnes.forEach(personne -> service.save(personne));
System.out.println("\ndisplaying the list and it's indexes after filling it");
service.displayPersonnes();
service.delete(1);
System.out.println("\ndisplaying the list and it's indexes after deletion");
service.displayPersonnes();
service.update(p3);
System.out.println("\ndisplaying the list and it's indexes after update");
service.displayPersonnes();
System.out.println("\nany id that you try to access that doesn't exist in the previous indexes");
System.out.println("will throw that error, because it doesn't exist, hence it isn't reachable");
service.findById(3);
service.findAll();
System.out.println(personnes);
// this throws an error
Output