Original question is here
I am reading in a UTF-8 file and parsing the contents of that file. If there is error in the file there is no point to continue and execution should stop. I have been suggested to throw IllegalArgumentException if there are problems with the contents, but the API doc says:
Thrown to indicate that a method has been passed an illegal or
inappropriate argument.
In my code, the argument would be the file (or actually the path) that I pass, is it correct to throw IllegalArgumentException in case something goes wrong while parsing? If not, what type of exception should I throw?
private char[][] readMazeFromFile(Path mazeFile) throws IOException {
if (!Files.isRegularFile(mazeFile) || !Files.isReadable(mazeFile)) {
throw new IllegalArgumentException("Cannot locate readable file " + mazeFile);
}
List<String> stringList = Files.readAllLines(mazeFile, StandardCharsets.UTF_8);
char[][] charMaze = new char[stringList.size()][];
for (int i = 0; i < stringList.size(); i++) {
String line = stringList.get(i);
if (line.length() != charMaze.length)
throw new IllegalArgumentException(String.format("Expect the maze to be square, but line %d is not %d characters long", line.length(), charMaze.length));
if (line.contains("B")) {
startX = i;
startY = line.indexOf("B");
}
if (line.contains("F")) {
endX = i;
endY = line.indexOf("F");
}
charMaze[i] = line.toCharArray();
}
if (startX == -1 || startY == -1)
throw new IllegalArgumentException("Could not find starting point (B), aborting.");
if (endX == -1 || endY == -1)
throw new IllegalArgumentException("Could not find ending point (F), aborting.");
return charMaze;
}
I think the first usage is correct:
if (!Files.isRegularFile(mazeFile) || !Files.isReadable(mazeFile)) {
throw new IllegalArgumentException("Cannot locate readable file "+mazeFile);
}
Since (as the documentation states) an invalid file was provided as the argument, this should throw an IllegalArgumentException.
Once you know you have an actual file that meets those requirements, I personally don't think that is a good exception to throw. This will cause other developers to question the type of argument that was given as opposed to the contents of the file. I guess your options are:
Keep it as is, just with very specific error messages explaining
why this was an invalid argument.
Use some other, potentially more applicable java exception such as java.text.ParseException, since it is the file parsing that is causing the error.
Create a custom exception class that more sufficiently describes the issue with the file, e.g. a MazeParseException (per the comments) or a FileFormatException.
I would expect the second or third option to be more beneficial if you anticipate several other developers executing your function.
Exceptions are mainly nothing but names, My best advice here would be to make your own.
Primary reason being that IllegalArgumentExceptions are unchecked exceptions because they extend java.lang.RuntimeException. They would just cause problems if you used them in a context like this.
(Source)
Change the method signature to
private char[][] readMazeFromFile(Path mazeFile) throws IOException, MazeParseException {...}
And all throw new IllegalArgumentException with throw new MazeParseException
(except for the first usage as per #Joel's answer)
The MazeParseException.java file:
package yourPackage.here;
import java.lang.Exception;
public class MazeParseException {
public MazeParseException() {
super();
}
public MazeParseException(String reason) {
super(reason);
}
}
The benefits here of using your own exception is that you can tag extra data along with the exception relating to your situation, for example you could add:
private int errorLineNum = null;
public MazeParseException(String reason, int lineNum) {
this(reason);
this.errorLineNum = lineNum;
}
public int getMalformedLine() {
return this.errorLineNum;
}
// And then update the toString() method to incorperate the errorLineNum
#Override
public String toString() {
StringBuilder sb = new StringBuilder(super.toString());
if(errorLineNum != null) {
sb.append("# line #");
sb.append(this.errorLineNum);
}
return sb.toString();
}
As JSON or XML library send their own execption if the file doesn't match what they are looking for (a JSON file or a XML one), I think you should do the same if doesn't match what you are looking for( an UTF-8 file ).
IllegalArgumentException should be use for internal problem in your code and should not be throw when your code have been debug. Also you should not catch an IllegalArgumentException and you will probably want to catch it in your program.
Related
My code does some arithmetic to convert a binary input to decimal output. I also made an exception class that extends NumberFormatException to throw an error if the input is not a 1 or 0. What I want is to throw the exception to a JTextField.
private void biTodeciActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String binary;
binary = binaryStringText.getText();
int total = 0;
for(int i = 0; i < binary.length(); i++)
{
if (binary.charAt(i) != '0' && binary.charAt(i) != '1')
{
throw new ParseMethods.BinaryNumberFormatException(binary.charAt(i)+" is not"
+" a valid binary input.");
}
else if(binary.charAt(i) == '1'){
total += Math.pow(2, (binary.length()-1)-i );
}
}
deciOut.setText(""+total);
}
Essentially, what you're trying to do won't work. The BinaryNumberFormatException doesn't declare that it throws any exceptions (and assuming you're using NetBeans), you won't be able to (easily) modify it.
You could wrap all you code in a try-catch block within the method, but that's just, well, kind of messy (IMHO)
Instead, what I might do, is create a class which does the conversation, something like...
public static class BinaryConverter {
public static String toDecimal(String binary) throws BinaryNumberFormatException {
//...
}
// Maybe a toBinary method as well...
}
for example. The toDecimal declares the fact that it will throw a BinaryNumberFormatException (although I think some kind of parse exception would be better)
Then in your action performed method, you could do something like...
private void biTodeciActionPerformed(java.awt.event.ActionEvent evt) {
try {
deciOut.setText(BinaryConverter.toDecimal(binaryStringText.getText()));
} catch (BinaryNumberFormatException exp) {
exp.printStackTrace();
deciOut.setText(exp.getMessage());
}
}
which would allow to deal with the operation been successful and unsuccessful in a more succinct manner.
This makes the code more reusable and easier to manager.
As an idea
Print exception directly into textfield in STRING format
deciOut.setText(""+exp);
I have this method in a "Point" class:
public Point sumPoints(Point p) {
if(dimension != p.getDimension())
throw new RuntimeException("Wrong dimensions.");
Double[] coord = new Double[dimension];
for(int i = 0; i < dimension; i++)
coord[i] = coordinates[i] + p.getCoord(i);
Point P = new Point(coord);
return P;
The idea is that points can be n-dimensional, so I should check that the dimensions of the points match before trying to add them up. The thing is that in the case that they don't match, I can't return a specific value (-1 for example, as I did in C), because the return type is Point.
What should I do in these cases? Is the RuntimeExeption an okay practice?
In short the answer to your question is yes. Exceptions is the accepted way to handle errors. There are a lot of Exceptions that are more specific that inherit from RuntimeException though.IllegalArgumentException comes to mind. Also you can write your own exceptions that inherit from a RuntimeException. And then of course there is a mammoth of a discussion about which Exception to use Unchecked (inheriting from RuntimeException) or checked (inheriting from Exception). Just type in Google "runtimeexception vs exception" and you will get a screenfull of links to keep you buisy :). Here is just one Example: difference between java.lang.RuntimeException and java.lang.Exception. There is no clear cut answer for that. You will have to choose on your own.
Exception handling is a much more elegant way to implement error handling in Java for a number of reasons.
Error codes
Returning error codes works well in C especially because of the ability to pass pointers as function parameters in C: In this way, you can e.g. create a new object inside the function and "return" it via the pointer passed to the function and let the function actually return a proper error code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int create_message_str(char *p_message, const size_t p_message_len)
{
int result = -1;
const char message[] = "Hello, world!";
if (NULL != p_message && strlen(message) <= p_message_len)
{
strcpy(p_message, message);
result = 0;
}
return result;
}
int main(int argc, char **argv)
{
int result = EXIT_FAILURE;
const size_t p_message_len = 13;
char *p_message = malloc(p_message_len * sizeof(char));
if (create_message_str(p_message, p_message_len) == 0)
{
printf("%s\n", p_message);
result = EXIT_SUCCESS;
}
else
{
fprintf(stderr, "%s\n", "Could not copy string to pointer memory.");
}
free(p_message);
return result;
}
In Java, however, you'd have to create an instance of e.g. some sort of mutable Supplier-like object for holding the reference to the object which would be referenced by the pointer in the C function:
public class ReferenceSwapper {
private static class MutableSupplier<T> implements Supplier<T> {
private T supplied;
public MutableSupplier(final T supplied) {
this.supplied = supplied;
}
#Override
public T get() {
return supplied;
}
public void set(final T supplied) {
this.supplied = supplied;
}
}
public static void main(final String[] args) {
final MutableSupplier<String> firstSupplier = new MutableSupplier<String>("foo");
final MutableSupplier<String> secondSupplier = new MutableSupplier<String>("bar");
System.out.println("Before reference swap: " + firstSupplier.get() + secondSupplier.get());
swapSupplied(firstSupplier, secondSupplier);
System.out.println("After reference swap: " + firstSupplier.get() + secondSupplier.get());
}
private static <T> void swapSupplied(final MutableSupplier<T> firstSupplier,
final MutableSupplier<T> secondSupplier) {
final T firstSupplied = firstSupplier.get();
final T secondSupplied = secondSupplier.get();
firstSupplier.set(secondSupplied);
secondSupplier.set(firstSupplied);
}
}
This code prints out:
Before reference swap: foobar
After reference swap: barfoo
As you can see, this is ridiculously complicated in Java due to its pass-by-value semantics.
Exceptions
However, Java offers a much higher-level way of defining error-handling behavior: Exceptions. Although some people debate if the idea of exceptions are a good thing or not and exception handling is really just fancy conditional logic, they are part of the Java language and can work well for reporting exceptional (i.e. erroneous) states.
As Andy Turner already mentioned, throwing an IllegalArgumentException would be the most natural way of reporting an error regarding the method's particular arguments which you shouldn't (normally) have to catch and handle: You'd be assuming that the people using sumPoints(Point p) are smart enough to pass the correct arguments or at least to suffer a program halt if they aren't so. However, if you do expect that this is a common occurrence is at least an occurrence which cannot be avoided purely through judicious programming (e.g. if the data is read from disk and might somehow get corrupted or not be available), then it might be better to throw a caught exception in order to force the calling method to handle the case where this happens.
the thing with exceptions in java is that you can code your own class that extends from Exception to use it in a class which you treat all kind of possible exceptions that could encounter your program then you just throw it.
example :
public class Erreur extends Exception{
String message;
public Erreur(String message){
this.message=message;
}
public String getMessage(){ return message;}
}
Then
public class Calcule {
public static double division(double x, double y) throws Erreur{
double r=0;
Erreur erre=new Erreur("can't divide by zero");
if(y==0) throw (erre);
else r=(x/y);
return r;
}
}
I've been working on a java project for the last couple days, and while things have gone smoothly to this point, I have hit a bit of a snag.
The point of the project is to create a query of sorts, where the user searches for a report using a GUI interface and the app spits out all related data.
Ex: report all where quality > 3
I use a StringTokenizer object to break the String down and evaluate each token. The first token MUST be report, the second token MUST be all, third token MUST be where, the fourth token MUST be either quality, basePrice or numInStock, the fifth token MUST be a relational operator(> < <= >= ==). We were instructed to throw custom checked exceptions if any of the tokens do not match what they should be. So far I have evaluated each token, and throw an Exception if the expected token is not what it should be.
Now once I reach the relational operator, i'm supposed to dump it into a new String called optok. The problem is, I can't seem to get my program to do this and i'm having a hard time figuring out how to do so. I've tried many different things and nothing seems to work.
The final goal is, once all the tokens have been evaluated and checked, to call a method to print the correct query and all data that goes along with said query. If one of the tokens doesn't match, an Exception is thrown.
Here is my code for evaluating each token, to check that it is in the correct format:
public void detectUserInput(String input) throws MissingInputException
{
if (input.equals(""))
{
System.out.println("Null input");
throw new MissingInputException();
}
else
{
System.out.println("Input is not null");
}
}//end detectUserInput
public void countTokens(String input) throws IncorrectFormatException
{
StringTokenizer tokenLength = new StringTokenizer(input, " ,");
if (tokenLength.countTokens() < 6)
{
throw new IncorrectFormatException();
}
}//end countTokens
public void evaluateTokens(String input) throws IllegalStartOfQueryException,
InvalidSelectorException,
InvalidQualifierException,
InvalidLValueException,
InvalidOperatorException
{
StringTokenizer testTokens = new StringTokenizer(input, " ,");
if (!testTokens.nextToken().equalsIgnoreCase("report"))
{
throw new IllegalStartOfQueryException();
}
else if (!testTokens.nextToken().equalsIgnoreCase("all"))
{
throw new InvalidSelectorException();
}
else if (!testTokens.nextToken().equalsIgnoreCase("where"))
{
throw new InvalidQualifierException();
}
else if (!testTokens.nextToken().matches("quality|numInStock|basePrice"))
{
throw new InvalidLValueException();
}
else if (!testTokens.nextToken().matches(">|<|>=|<=|=="))
{
throw new InvalidOperatorException();
}
//here is where I try to take the relational operator
//and dump it into optok, after all the previous input
//has been validated, but it doesnt work :(
while (testTokens.hasMoreTokens())
{
tok = testTokens.nextToken();
if (tok.matches("<|>|>=|<=|=="))
{
optok = tok;
}
}
}//end evaluateTokens
And here is the actionPerformed() of my program that reacts when the user types their query into the TextField and presses the GO! JButton :
private class ButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent ev)
{
if (ev.getSource() == goBtn)
{
input = queryFld.getText();
try
{
detectUserInput(input);
countTokens(input);
evaluateTokens(input);
}
catch (MissingInputException mie)
{
errorFld.setText("Enter an expression");
queryFld.setText("");
System.err.println(mie);
mie.printStackTrace();
}
catch (IncorrectFormatException ife)
{
errorFld.setText("Too few terms");
queryFld.setText("");
System.err.println(ife);
ife.printStackTrace();
}
catch (IllegalStartOfQueryException isqe)
{
errorFld.setText("Word REPORT expected");
queryFld.setText("");
System.err.println(isqe);
isqe.printStackTrace();
}
catch (InvalidSelectorException ise)
{
errorFld.setText("Selector must be ALL");
queryFld.setText("");
System.err.println(ise);
ise.printStackTrace();
}
catch (InvalidQualifierException iqe)
{
errorFld.setText("Qualifier error - keyword WHERE missing");
queryFld.setText("");
System.err.println(iqe);
iqe.printStackTrace();
}
catch (InvalidLValueException ilve)
{
errorFld.setText("Invalid query. quality, numInStock, "
+ "or basePrice expected");
queryFld.setText("");
System.err.println(ilve);
ilve.printStackTrace();
}
catch (InvalidOperatorException ioe)
{
errorFld.setText("InvalidOperatorException. < <= > >= == expected");
queryFld.setText("");
System.err.println(ioe);
ioe.printStackTrace();
}
}
}//end actionPerformed
}//end ButtonHandler
I apologize if this seems trivial, but i'm having a really hard time figuring it out for some reason. I appreciate any input or suggestions. If i'm missing any info needed please let me know and i'll add it asap. Also, here are the instructions for this segment:
11) Now, focus on the evaluateAll method. Get the next token. It should be any one of 3 words:
“basePrice” or “quality” or “numInStock” . If it is not, place the message “Invalid query, quality, numInStock or basePrice expected. If is one of those 3 words, you expect a relational operator, so get the next token, but save it in a new String, call it optok. If it is not a correct operator, place the message “invalid query,
You now have two Strings: token which is either “basePrice” or “quality” or “numInStock” and an optok which is one of the 5 relational operators listed above.
Thanks in advance :)
You didn't post a stacktrace, so I'm guessing you're not having an exception, and reading from your code I'm trying to understand what could be happening .. so I might be wrong.
It seems to me that you are using a tokenizer. A tokenizer is like a stream, once you call nextToken() it returns the token, and unless you save it somewhere the next call to nextToken() will make the previous one not accessible.
So, where you make :
else if (!testTokens.nextToken().matches("quality|numInStock|basePrice"))
{
throw new InvalidLValueException();
}
else if (!testTokens.nextToken().matches(">|<|>=|<=|=="))
{
throw new InvalidOperatorException();
}
You are consuming the tokens. As a result, when you get to the while :
while (testTokens.hasMoreTokens()) {
All the tokens are consumed, so it will not iterate here.
You should instead save your tokens in variables, so that you can both check and the use them :
StringTokenizer testTokens = new StringTokenizer(input, " ,");
if (!testTokens.nextToken().equalsIgnoreCase("report"))
{
throw new IllegalStartOfQueryException();
}
else if (!testTokens.nextToken().equalsIgnoreCase("all"))
{
throw new InvalidSelectorException();
}
else if (!testTokens.nextToken().equalsIgnoreCase("where"))
{
throw new InvalidQualifierException();
}
// TODO here i use local variables, since you need to use these outside this method,
// maybe use class fields or whatever else
String subject = testTokens.nextToken();
String opttok = testTokens.nextToken();
if (!subject.matches("quality|numInStock|basePrice"))
{
throw new InvalidLValueException();
}
else if (!opttok.matches(">|<|>=|<=|=="))
{
throw new InvalidOperatorException();
}
// done, now you have opttok and subject
Consider this simple program. The program has two files:
File Vehicle.java
class Vehicle {
private int speed = 0;
private int maxSpeed = 100;
public int getSpeed()
{
return speed;
}
public int getMaxSpeed()
{
return maxSpeed;
}
public void speedUp(int increment)
{
if(speed + increment > maxSpeed){
// Throw exception
}else{
speed += increment;
}
}
public void speedDown(int decrement)
{
if(speed - decrement < 0){
// Throw exception
}else{
speed -= decrement;
}
}
}
File HelloWorld.java
public class HelloWorld {
/**
* #param args
*/
public static void main(String[] args) {
Vehicle v1 = new Vehicle();
Vehicle v2 = new Vehicle();
// Do something
// Print something useful, TODO
System.out.println(v1.getSpeed());
}
}
As you can see in the first class, I have added a comment ("// throw exception") where I would like to throw an exception. Do I have to define my own class for exceptions or is there some general exception class in Java I can use?
You could create your own Exception class:
public class InvalidSpeedException extends Exception {
public InvalidSpeedException(String message){
super(message);
}
}
In your code:
throw new InvalidSpeedException("TOO HIGH");
You could use IllegalArgumentException:
public void speedDown(int decrement)
{
if(speed - decrement < 0){
throw new IllegalArgumentException("Final speed can not be less than zero");
}else{
speed -= decrement;
}
}
Well, there are lots of exceptions to throw, but here is how you throw an exception:
throw new IllegalArgumentException("INVALID");
Also, yes, you can create your own custom exceptions.
A note about exceptions. When you throw an exception (like above) and you catch the exception: the String that you supply in the exception can be accessed throw the getMessage() method.
try{
methodThatThrowsException();
}catch(IllegalArgumentException e)
{
e.getMessage();
}
It really depends on what you want to do with that exception after you catch it. If you need to differentiate your exception then you have to create your custom Exception. Otherwise you could just throw new Exception("message goes here");
The simplest way to do it would be something like:
throw new java.lang.Exception();
However, the following lines would be unreachable in your code. So, we have two ways:
Throw a generic exception at the bottom of the method.
Throw a custom exception in case you don't want to do 1.
Java has a large number of built-in exceptions for different scenarios.
In this case, you should throw an IllegalArgumentException, since the problem is that the caller passed a bad parameter.
You can define your own exception class extending java.lang.Exception (that's for a checked exception - these which must be caught), or extending java.lang.RuntimeException - these exceptions does not have to be caught.
The other solution is to review the Java API and finding an appropriate exception describing your situation: in this particular case I think that the best one would be IllegalArgumentException.
It depends. You can throw a more general exception, or a more specific exception. For simpler methods, more general exceptions are enough. If the method is complex, then, throwing a more specific exception will be reliable.
I wrote a code which checks all kinds of conditions.
If it meets the condition it does what it is supposed to, otherwise I want it to throw an
exception.
Is there any special syntax for that? Otherwise the compiler wants me to return any array,
which I don't want to, due to the pre-condition.
Here is part of my code:
public static int [] code(int[]arr){
if ((arr!=null)&&(chack4and5(arr))&&(arr[arr.length-1]!=4)&&(TwoFours(arr))){
int k=0;
for(int i = 0; i<=arr.length-1; i++){
if (arr[i] == 4){
int place= pos(arr,k);
arr[place]=arr[i+1];
arr[i+1]=5;
k=k+3;
}
}
return arr;
}
else {
System.out.println("Please enter a legal array which matches the pre- conditions");
}
}
}
The way to throw an exception is
throw new IllegalArgumentException(
"Please enter a legal array which matches the pre- conditions");
IllegalArgumentException is a Java runtime exception suitable for the current situation, but of course you can choose another one, or create and use your own type too. The only restriction is that it must be a subclass of java.lang.Exception.
I would rearrrange your code though to check the preconditions first, then proceed if everything's fine - I find this more readable:
if (arr == null || !chack4and5(arr) || arr[arr.length-1] == 4 || !TwoFours(arr)) {
throw new IllegalArgumentException(
"Please enter a legal array which matches the pre- conditions");
}
int k=0;
for(int i = 0; i<=arr.length-1; i++){
if (arr[i] == 4){
int place= pos(arr,k);
arr[place]=arr[i+1];
arr[i+1]=5;
k=k+3;
}
}
return arr;
(In fact, I would even prefer extracting the precondition check into a separate method - but I leave this to you.)
throw new IllegalArgumentException(
"Please enter a legal array which matches the pre- conditions")
java.langIllegalArgumentException is a RuntimeException that means some of the arguments are not as they are expected to be. Since it is an unchecked exceptions, your callers are not forced to handle it in any way (as opposed to checked exceptions)
You can throw an Exception by yourself. Maybe the best way to do this is defining a custom exception and then throwing it. If you don't want to do that use an IllegalArgumentException.
Here an example of a custom exception:
public static int [] code(int[]arr) {
if ((arr!=null)&&(chack4and5(arr))&&(arr[arr.length-1]!=4)&&(TwoFours(arr))){
int k=0;
for(int i = 0; i<=arr.length-1; i++){
if (arr[i] == 4){
int place= pos(arr,k);
arr[place]=arr[i+1];
arr[i+1]=5;
k=k+3;
}
}
return arr;
}
else {
throw new MyException("No legal array");
}
}
}
And here your custom exception:
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
If the exception is that something about your arguments is illegal, then throw an IllegalArgumentException:
throw new IllegalArgumentException("descriptive message")
You may want to take a look at Oracle's tutorials on exceptions.
To throw an exception, you use the throw keyword.
To mark that a method may throw an exception, use the throws keyword, like
public static void foo() throws SomeException
You can throw exception with this line
throw new SomeKindOfException("Exception description"); // or any other exception, also yours...
But you need to specify at the method declaration:
public static int [] code(int[]arr) throws SomeKindOfException{
See Oracle tutorial for more