How do I get around the limitation of having to place super constructor in the first line?
public NoWheelsException(Car[] carArray){
String holder = "";
for (int i=0; i<carArray.length; i++) {
if (i == carArray.length - 1) {
holder = holder + carArray[i].name;
}else{
holder = holder + carArray[i].name + ", ";
}
}
String message = holder + " has/have no wheels.";
super(message);
}
Written above is the ideal scenario that I'd have for my code, with the super constructor at the end. Although, since super has to be the first statement, I cannot figure out how to develop the string out of the array inline. I can't straight up use .toString()
as there's certain criteria into what the string should look like. I've managed to figure out everything regarding Exceptions except this itty bitty detail. Any help would be greatly appreciated!
Update
I got suggested to try Strin.join in order to link them together although unfortunately the object reference names differ from the name variable in the array objects...
Solution 1:
One way is to create a private static method, since static methods exist irrespective of constructors and instantiation:
public NoWheelsException(Car[] carArray){
super(buildMessageFrom(carArray));
}
private static String buildMessageFrom(Car[] cars) {
StringBuilder message = new StringBuilder();
String separator = "";
for (Car car : cars) {
message.append(separator);
message.append(car.name);
separator = ", ";
}
return message.toString();
}
(When building a String in a loop, StringBuilder is much more efficient than string concatenation. Each iteration of ‘holder = holder + …’ would create a new String object that eventually needs to be garbage collected.)
If you’re comfortable with Streams, you can do it all on one line:
public NoWheelsException(Car[] carArray){
super(Arrays.stream(carArray).map(c -> c.name).collect(Collectors.joining(", ")));
}