So, for a homework assignment, our professor wants us to try inserting an integer into an array of Strings:
public boolean addPerson(V person, int number)throws IllegalArgumentException{
if(numEntries < people.length){
people[numEntries] = person;
phones[numEntries] = number;
numEntries++;
return true;
}
return false;
}
public static void main(String[] args){
PhoneBook<String> names = new PhoneBook<String>();
PhoneBook<Integer> ssn = new PhoneBook<Integer>();
names.addPerson("john", 1235681213);
ssn.addPerson(123324567, 2048);
Integer soc = 132546789;
try{
names.addPerson(soc, 1996);
}
catch(IllegalArgumentException e){
System.out.println("You cannot enter a Social Security Number "
+ "into the Name phone book!");
}
But, this isn't working, and I still get the same error as without the try-catch. Any idea what I'm doing wrong?
EDIT
Sorry guys, I probably should've included the code for the addPerson method. I don't really know how to deal with exceptions yet.
What your professor likely wants you to observe is a compilation error. An array's type is fixed at instantation time, and will not change. The array will only ever accept whatever type it has been declared to accept, and nothing else.
Minor rant about exceptions to follow from here.
Let's have a quick chat about checked and unchecked exceptions. There is a difference between these two, and mixing them up can be painful at times.
Let's start with the checked exceptions. These are the exceptions that you must either explicitly catch yourself, or declare them to be thrown. Things along those lines are IOException, FileNotFoundException*, and a few others - pretty much anything that extends from the Exception class.
Java is telling you that you have the ability to recover from this error, and you as a good developer should ensure that your program does.
There are also unchecked exceptions; anything that extends RuntimeException or Error. These do not need to be declared to be thrown, as they occur during the runtime of the application, and there's really no guarantee if the program should recover from this error. An example of this would be ArithmeticException; should your application really recover if it tried to divide by zero? What state would it be in?
There are also some you really shouldn't be catching at all - what would you return to if you managed to catch an OutOfMemoryError? There isn't much you really can do at that point!
Now, to your code: you've declared an unchecked exception to be thrown. That's valid syntax, but Java isn't going to just arbitrarily throw the exception for you, because there isn't anything in that block of code that would just throw it. At worst, you could get an ArrayIndexOutOfBoundsException, but that's no IllegalArgumentException.
In order to actually throw that unchecked exception, you'd need to explicitly throw it:
throw new IllegalArgumentException();
...and you'd also need a good reason to do so. Exceptions are expensive.
*: I realize that FileNotFoundException is-an IOException. It's still checked.
Related
I'm worried that this is a runtime exception so it should probably be used sparingly.
Standard use case:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
But that seems like it would force the following design:
public void computeScore() throws MyPackageException {
try {
setPercentage(userInputPercent);
}
catch(IllegalArgumentException exc){
throw new MyPackageException(exc);
}
}
To get it back to being a checked exception.
Okay, but let's go with that. If you give bad input, you get a runtime error. So firstly that's actually a fairly difficult policy to implement uniformly, because you could have to do the very opposite conversion:
public void scanEmail(String emailStr, InputStream mime) {
try {
EmailAddress parsedAddress = EmailUtil.parse(emailStr);
}
catch(ParseException exc){
throw new IllegalArgumentException("bad email", exc);
}
}
And worse - while checking 0 <= pct && pct <= 100 the client code could be expected to do statically, this is not so for more advanced data such as an email address, or worse, something that has to be checked against a database, therefore in general client code cannot pre-validate.
So basically what I'm saying is I don't see a meaningful consistent policy for the use of IllegalArgumentException. It seems it should not be used and we should stick to our own checked exceptions. What is a good use case to throw this?
The API doc for IllegalArgumentException:
Thrown to indicate that a method has been passed an illegal or inappropriate argument.
From looking at how it is used in the JDK libraries, I would say:
It seems like a defensive measure to complain about obviously bad input before the input can get into the works and cause something to fail halfway through with a nonsensical error message.
It's used for cases where it would be too annoying to throw a checked exception (although it makes an appearance in the java.lang.reflect code, where concern about ridiculous levels of checked-exception-throwing is not otherwise apparent).
I would use IllegalArgumentException to do last ditch defensive argument checking for common utilities (trying to stay consistent with the JDK usage). Or where the expectation is that a bad argument is a programmer error, similar to an NullPointerException. I wouldn't use it to implement validation in business code. I certainly wouldn't use it for the email example.
When talking about "bad input", you should consider where the input is coming from.
Is the input entered by a user or another external system you don't control, you should expect the input to be invalid, and always validate it. It's perfectly ok to throw a checked exception in this case. Your application should 'recover' from this exception by providing an error message to the user.
If the input originates from your own system, e.g. your database, or some other parts of your application, you should be able to rely on it to be valid (it should have been validated before it got there). In this case it's perfectly ok to throw an unchecked exception like an IllegalArgumentException, which should not be caught (in general you should never catch unchecked exceptions). It is a programmer's error that the invalid value got there in the first place ;) You need to fix it.
Throwing runtime exceptions "sparingly" isn't really a good policy -- Effective Java recommends that you use checked exceptions when the caller can reasonably be expected to recover. (Programmer error is a specific example: if a particular case indicates programmer error, then you should throw an unchecked exception; you want the programmer to have a stack trace of where the logic problem occurred, not to try to handle it yourself.)
If there's no hope of recovery, then feel free to use unchecked exceptions; there's no point in catching them, so that's perfectly fine.
It's not 100% clear from your example which case this example is in your code, though.
Treat IllegalArgumentException as a preconditions check, and consider the design principle: A public method should both know and publicly document its own preconditions.
I would agree this example is correct:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
If EmailUtil is opaque, meaning there's some reason the preconditions cannot be described to the end-user, then a checked exception is correct. The second version, corrected for this design:
import com.someoneelse.EmailUtil;
public void scanEmail(String emailStr, InputStream mime) throws ParseException {
EmailAddress parsedAddress = EmailUtil.parseAddress(emailStr);
}
If EmailUtil is transparent, for instance maybe it's a private method owned by the class under question, IllegalArgumentException is correct if and only if its preconditions can be described in the function documentation. This is a correct version as well:
/** #param String email An email with an address in the form abc#xyz.com
* with no nested comments, periods or other nonsense.
*/
public String scanEmail(String email)
if (!addressIsProperlyFormatted(email)) {
throw new IllegalArgumentException("invalid address");
}
return parseEmail(emailAddr);
}
private String parseEmail(String emailS) {
// Assumes email is valid
boolean parsesJustFine = true;
// Parse logic
if (!parsesJustFine) {
// As a private method it is an internal error if address is improperly
// formatted. This is an internal error to the class implementation.
throw new AssertError("Internal error");
}
}
This design could go either way.
If preconditions are expensive to describe, or if the class is intended to be used by clients who don't know whether their emails are valid, then use ParseException. The top level method here is named scanEmail which hints the end user intends to send unstudied email through so this is likely correct.
If preconditions can be described in function documentation, and the class does not intent for invalid input and therefore programmer error is indicated, use IllegalArgumentException. Although not "checked" the "check" moves to the Javadoc documenting the function, which the client is expected to adhere to. IllegalArgumentException where the client can't tell their argument is illegal beforehand is wrong.
A note on IllegalStateException: This means "this object's internal state (private instance variables) is not able to perform this action." The end user cannot see private state so loosely speaking it takes precedence over IllegalArgumentException in the case where the client call has no way to know the object's state is inconsistent. I don't have a good explanation when it's preferred over checked exceptions, although things like initializing twice, or losing a database connection that isn't recovered, are examples.
As specified in oracle official tutorial , it states that:
If a client can reasonably be expected to recover from an exception,
make it a checked exception. If a client cannot do anything to recover
from the exception, make it an unchecked exception.
If I have an Application interacting with database using JDBC , And I have a method that takes the argument as the int item and double price. The price for corresponding item is read from database table. I simply multiply the total number of item purchased with the price value and return the result. Although I am always sure at my end(Application end) that price field value in the table could never be negative .But what if the price value comes out negative? It shows that there is a serious issue with the database side. Perhaps wrong price entry by the operator. This is the kind of issue that the other part of application calling that method can't anticipate and can't recover from it. It is a BUG in your database. So , and IllegalArguementException() should be thrown in this case which would state that the price can't be negative.
I hope that I have expressed my point clearly..
Any API should check the validity of the every parameter of any public method before executing it:
void setPercentage(int pct, AnObject object) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("pct has an invalid value");
}
if (object == null) {
throw new IllegalArgumentException("object is null");
}
}
They represent 99.9% of the times errors in the application because it is asking for impossible operations so in the end they are bugs that should crash the application (so it is a non recoverable error).
In this case and following the approach of fail fast you should let the application finish to avoid corrupting the application state.
I am trying to understand WHY to throw certain exceptions. What does it matter which one I choose to throw?
For example
//simple division method - a/b
public static double divide(double a, double b){
if(b == 0)
throw new IllegalArgumentException("b = 0");
return a/b;
}
vs
//simple division method - a/b
public static double divide(double a, double b){
if(b == 0)
throw new IllegalArithmeticException("b = 0");
return a/b;
}
(Apologies if there are errors in the code - I threw it together quickly. I'm not actually interested in the method itself.)
Does it matter which exception I choose? It seems like it could be anything - even if I used arrayIndexOutOfBoundsException, it would still stop the program and print what I want it to print.
Thanks for any help.
It's worth discussing what the difference is between a checked and an unchecked exception is, to hammer home a critical point of what exception to throw.
Let's say that you're attempting to read a file, and for whatever reason, the file isn't found. Java has a convenient FileNotFoundException that you can use to explicitly inform that the file isn't found. It's also one of the exceptions which extend (through its hierarchy) Exception, meaning that if a method states that this exception is thrown, it must be dealt with either by catching it or declaring it to be thrown elsewhere.
Then, there's the ArithmeticException, which is a runtime exception (it extends RuntimeException) - no methods need to declare this to be thrown, and you're not required to catch it explicitly, since this class of exceptions indicate an error in the code. It can come up, and in actuality, if anything were to try and catch a runtime exception, it'd look a little bit suspect.
In the context of your problem, you're basically stomping over the natural throwing of the ArithmeticException by forewarning the user of valid input. It's likely acceptable to do something like this, but for this context, you actually don't need to throw anything yourself. If someone decides to pass b = 0 into the method, they'll get the ArithmeticException.
There are existing conventions to follow based on exceptions - be as specific about the problem as possible, and offer a way to recover if appropriate - so in this scenario, if you had to throw a specific exception, I'd recommend IllegalArgumentException, since the argument b = 0 isn't acceptable when dividing or doing modulo. However, I'd also recommend that it be caught in a method outside of this instead, since the input is really suspect and it should be ideally sanitized before it makes its way to this method.
Well, from a company's point of view, it does matter what exception you're throwing. Because tecnically, you create programs for the users to work on it and if the user enters undesirable input then he/she will be able to get what mistake he/she has made.
It works as a note for the user to correct the mistakes.
I was wondering what is the proper convention for handling a try/catch block. It is pretty obvious what should be within the try block but what about the catch block?
Can I write a message to the user like the following:
do {
try {
System.out.println("Pi to the number of decimal places:");
Scanner in = new Scanner(System.in);
userNth = in.nextInt();
} catch (Exception e) {
System.out.println("Error: Enter a number between 1 and 100");
}
} while(userNth < 1 || userNth > piDecimals);
Or is this bad practice?
Exception-handling is not the place to make rash assumptions; usually by the time this part of your code has been executed it's because something unanticipated has happened, this is when you want to be most careful to be accurate about detecting and recording what happened so that you can tell what needs fixing.
The choice of Exception as the type of exception that gets caught is too broad. The method you're calling throws 3 different exceptions for distinctly different reasons; only one of which is something that should be caught here. Also unchecked exceptions like NullPointerException will get caught by this. If you were to add some code to this catch block that inadvertently introduced a NPE it would be hard to figure out what went wrong. Your overbroad catch can result in bugs not being found or errors not getting handled properly.
(Btw Makoto makes a good point that nextInt isn't what you should be calling here anyway.)
Not logging the exception can be acceptable in narrow cases where you're certain of what the exception means (for instance, if you caught InputMismatchException, or NumberFormatException in Makoto's example code). But in combination with catching Exception it has the capacity to hide errors and cause confusion.
You likely chose to catch Exception because handling a bunch of different checked exceptions, most of which seemed unlikely to ever happen anyway, seemed like an intolerable nuisance. Providing a consistent way of handling and logging exceptions will help, by providing a reasonable default case for exceptions you don't know what to do with. That way if you see an exception you just can't handle, you always have the option of letting it be thrown (possibly catching it and wrapping it in an unchecked exception), knowing that if thrown it will get logged and end your program.
For a very small command-line program sometimes it's entirely ok to let exceptions that you can't handle be thrown from main (by adding throws Exception to the main method). This is ok for toy examples, small school projects, etc.; I'd only use it in production code if there was a plan for logging the output (like a batch file that redirects stderr to a file):
public static void main(String... args) throws Exception {
... application code
}
In most cases all the main method code should be placed in a try block where any Throwable is caught and logged:
public static void main(String... args) {
try {
... application code here
}
catch (Throwable t) {
logger.log(t);
}
}
Either alternative makes it less tempting for you to inappropriately swallow inconvenient checked exceptions.
Simple Answer: what you wrote is fine
Longer Answer: try-catch blocks are for executing code that may throw an exception, and then handling said exception if it occurs. In general, the catch block should have code that handles the exception however you need to handle it. If the statement you currently have is how you want to respond to an exception, then it's fine by convention. Some common things to do in a catch block are:
Throw another exception that encapsulates the thrown exception. (I often do this when parsing so that there can be a single ParseException)
Throw a runtime exception encapsulating the thrown exception and let java's default uncaught exception handler deal with it. (I do this a lot when I'm writing quick temporary programs and I don't want to deal with checked exceptions)
Pass it to some generic handler in your program, such as a GUI to display the error, etc.
call printStacktrace on it
But anything that fits your exception-handling needs is fine
In all actuality, this code is not going to function the way you intend it to. There are two key reasons for this:
nextInt() blocks until it receives an integer; that is, it's not going to care about what input you give it until it reads an integer, and
Even if this were to be okay, depending on how you initialize userNth and piDecimals, one or both of those variables may not be defined, thus preventing compilation.
Also, don't catch Exception. Be as specific as you can when catching exceptions, since Exception also includes some nifty and dangerous RuntimeExceptions like NullPointerException.
What you're looking to do:
Take in an integer input
If the user enters a non-integer, tell them they need to enter an integer
Keep doing this while userNth < 1 || userNth > piDecimals.
To that, we should look to get the right exception thrown by parsing the input as a string first, then as an Integer:
try {
System.out.println("Pi to the number of decimal places:");
userNth = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
System.out.println("Error: Enter a number between 1 and 100");
// You have to set this value to something so that userNth is defined!
userNth = Integer.MAX_VALUE;
}
The other part to this is that you have to decide what message you show if userNth > 1 && userNth < piDecimals, since your try...catch isn't going to cover that. This, I leave as an exercise for the reader.
This is my first time posting a question so I apologize if I am vague or unclear. I'm still learning some of the essentials of Java and I came across a tutorial online regarding exceptions. The entire thing can be found here: Java World: Exceptions in Java.
This may be a dumb question but I'm having difficulty understanding it.
class VirtualCafe {
public static void serveCustomer(VirtualPerson cust,
CoffeeCup cup) {
try {
cust.drinkCoffee(cup);
System.out.println("Coffee tastes just right.");
}
catch (UnusualTasteException e) {
System.out.println(
"Customer is complaining of an unusual taste.");
String s = e.getMessage();
if (s != null) {
System.out.println(s);
}
// Deal with an unhappy customer...
}
}
}
I'm having trouble understanding why would you want to store a string object and then have it print if the previous println seemed like it took care of the problem. What exactly does the second println print out? drinkCoffee() throws a few types of Exceptions including UnusualTasteException. I'd appreciate any feedback!
Here's the code for UnusualTasteExpection:
class UnusualTasteException extends Exception {
UnusualTasteException() { }
UnusualTasteException(String msg) {
super(msg);
}
}
To give an example, if the exception is thrown like this:
throw new UnusualTasteException("The coffee is very bitter");
the println() you're asking about would print out The coffee is very bitter, which is more informative than the generic "unusual taste" message.
This code (sort of) highlights a couple of things:
Catching exceptions and getting meaningful information from them
Dealing with null when it's undesirable to allow around
So, let's be explicit - the code in the catch block is dealing with whatever error message we bring back from the drinkCoffee method thrown by the UnusualTasteException. That said, we print a more generic message about the fact that the customer had an unusual taste with their coffee.
The second println concerns if we had anything meaningful to learn from the exception; a message or a clue or something. It could also be the case that someone passed in null to the constructor in this manner:
throw new UnusualTasteException((String) null);
...or more innocuously:
String msg = null;
throw new UnusualTasteException(msg);
If we don't have anything meaningful to print out, then we don't print it out. We also want to avoid repeated calls to the method, so we store the result of the call into a variable. This is what the second block accomplishes.
As a general aside, this is considered using exceptions as flow control, because there are any number of ways to handle this scenario appropriately (an enum for satisfaction of taste, or a boolean for whether they liked it or not stored on the drinker). In general, it's considered poor practice because exceptions are incredibly expensive to generate, and should be reserved for something truly exceptional.
So your code (within drinkCoffee method) would be doing something like to throw an exception:
throw new UnusualTasteException ("Weird coffee taste!!!");
If you see Exception class's parent i.e. Throwable has a field called detailMessage and then when you call above constructor to throw an exception, it will set detailMessage field.
And that's what you are using in your second print statement. So your print statement would print "Weird coffee taste!!!"
By doing so, you get exact string and intention of exception. And you might be throwing same exception from tea, lemon etc. but if you were processing flow for coffee, you see that it was weird taste of coffee and not lemon or tea and so on.
Suppose I have a MyException class that subclasses Exception. I'm using this class to include contextual information when errors occur in my code.
I typically use it to wrap one of the "standard" exception classes. For example, if an error happens during input validation, I will do something like
if (invalidInput())
throw new MyException(new IllegalArgumentException(), arg1, arg2, ...);
But my IDE (Intellij IDEA) warns me that instantiating an unchecked exception (IllegalArgumentException in this example) without throwing it is bad, but doesn't tell me why.
So how sinful is it to instantiate an exception without throwing it? To which circle of hell will I go?
You might be better off throwing an instance of IllegalArgumentException, in this case that's what it's for:
if (invalidInput())
new IllegalArgumentException("Invalid argument " + x + ", expected ...");
Or otherwise extending, IllegalArgumentException instead of Exception, it if you want to enhance it with custom properties.
public class MyIllegalArgumentException extends IllegalArgumentException {
public MyIllegalArgumentException(Object arg...) { .... }
}
Both cases provide a leaner, more meaningful, class model.
Update:
given your comment about wanting to supply contextual info with the thrown exception - you can do this by supplying your custom exception object as the Throwable argument to the standard exceptions contructor i.e. flip it round so: instead of wrapping the relevant standard exception in your exception, you should wrap your exception in the relevant standard exception.
if (invalidInput())
new IllegalArgumentException("Invalid argument " + x + ", expected ...", new MyContextException(a,b,c));
(where a,b & c are the various bits of context you want to transmit).
This way you (re)use a meaningful & appropriate, exception at all points in the code, but you transmit the contextual information that you may want to use further up the stack when handling/logging the exception.
You're not going to hell from instantiating an exception the way you're doing it. I'm sure the warning is there to make sure you use your exceptions as exceptions and not just any object.
However, you're going to hell for having MyException not subclassing RuntimeException ;)
This isn't bad at all.
Like most warnings, they're there to indicate situations that are less likely to legitimately occur, than they are to be someone invoking them by mistake. Another recent example on SO was the warnings about synchronizing on a local variable; it's not often you want to do that and it's easy to mess up concurrency by doing it inadvertently.
IntelliJ is just warning you that exceptions are usually created to be thrown immediately, so if you aren't doing this it flags that perhaps your code is behaving unexpectedly. In your case, you're doing exactly what's right so feel free to ignore the warning. (In fact in my project the structure means I often create exceptions without throwing them for various reasons, so I downgraded the warning to an "info" level in IntelliJ's config).
It's a strange construct, but there is a solution to trick the compiler.
Rewrite your invalidInput method to throw the IAE
private void checkInput() throws IllegalArgumentException {
if (...)
throw new IllegalArgumentException();
and:
try {
checkInput();
} catch (IllegalArgumentException ex) {
throw new MyException(ex, arg1, arg2, ...);
}
IntelliJ does tell you why. You just have to read the description for the inspection.
This inspection reports any instances of Throwable instantiation, where the created Throwable is never actually thrown. Most often this is the result of a simple mistake.