Error Checking a project in Java - java

My goal in the below code is to check for input that is longer than two places after the decimal point, then throw an exception. I cant seem to get it correct though. I am trying to use indexOf to get to the decimal point and then I want to check the length of the portion after it. If it is greater than 2 I want it to throw the exception. Anybody have some tips for this situation?
public ChangeJar(final String amount) {
int i = amount.indexOf('.');
String temp = amount.substring(i + 2);
if(temp.length() > 2 ){
throw new IllegalArgumentException("Too many decimal places!");
}
if (amount == null || Double.parseDouble(amount) < 0) {
throw new IllegalArgumentException("amount cannot be null!");
}
double amt;
try {
amt = Double.parseDouble(amount);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException("Invalid entry. Format is 0.00.");
}
amountHelper(amt);
}
I also wanted to know how I could add error checking to this constructor as I dont want null inputs. I get an error when trying to add error checking that says the constructor call must be the first statement in the method.My code for the constructor is:
public ChangeJar(final ChangeJar other){
if(other == null){
throw new IllegalArgumentException("Values cannot be null!");
}
this(other.quarters, other.dimes, other.nickels, other.pennies);
}
All suggestions are appreciated!

As Java does not allow to put any statements before the super or constructor calls in a constructor. Hence you cant do this:
public ChangeJar(final ChangeJar other){
if(other == null){
throw new IllegalArgumentException("Values cannot be null!");
}
this(other.quarters, other.dimes, other.nickels, other.pennies);
}
You may add the check in the constructor that you are calling.

Related

Java: missing return statement after try-catch [duplicate]

This question already has answers here:
Java Compiler Error: Missing Return Statement
(2 answers)
Closed 4 years ago.
I'm using the code below in a Triangle class to allow the user to set the first, second, or third point of a declared Triangle.
public Point get(String p) throws IllegalArgumentException {
IllegalArgumentException e = new IllegalArgumentException();
try {
if (p == "first") { return first; }
else if (p == "second") { return second; }
else if (p == "third") { return third; }
else { throw e; }
}
catch (e) {
System.out.println("Error: " + e);
}
}
The compiler is telling me:
Triangle.java:41: error: missing return statement
}
^
But I thought the point of the catch statement was to be able to catch an error and return a string describing the error, without having to worry about matching the function's return type.
Because you're missing a return statement.
The method declares that it returns something, so it must return something (or throw an exception). The compiler can't guarantee that any of the return statements in the try block will be reached if an exception is thrown before any of them execute. So the catch block also needs to return something (or throw an exception, or return something after the try/catch construct entirely).
Edit: Looking again, you're also potentially missing a return in the try block. (If you don't have one after the entire try/catch structure.) What if none of the conditions in the if/else structure are satisfied? Nothing is returned. Which is invalid.
Basically, all logical paths must result in a valid exit of the method. You've missed two such paths.
You're not returning anything in your function on several paths.
But I thought the point of the catch statement was to be able to catch an error and return a string describing the error, without having to worry about matching the function's return type.
That's not at all what a try-catch does, and moreover your function is declared to return a Point not a String.
try-catch simply "catches" a Throwable (Error or Exception) and allows you to run some code when it is thrown instead of simply terminating the application with an Uncaught Exception/Error.
You need to return some value from your function after the try-catch there is no way to return a string, nor is there a language construct in place that behaves like you've explained your understanding of try-catch.
Also your code cna't actually throw an IllegalArgumentException so your catch block will never get called. In this case, it sounds like what you want is instead something like this
public Point get(String p) throws IllegalArgumentException {
if (p == null) { throw new IllegalArgumentException(); }
if (p.equals("first")) { return first; }
else if (p.equals("second")) { return second; }
else if (p.equals("third")) { return third; }
else { throw new IllegalArgumentException(); }
}
The code could then be called like so
Point p;
try {
p = get("notFirst");
} catch (IllegalArgumentException ex) {
//oh no, we gave a bad argument, and the method told us nicely.
}
You are missing two parts:
1. A return statement in try block for else condition
2. Catch block doesn't lead to a return statement or a throw statement
I don't know if type of first, second, third variables are string or Point, but you should return with Point, because your function is :
public Point get(String p) {
...
}
You have three if statements. What happens when the input doesn't satisfy any of those? Your method doesn't have a return statement for that case.

Evaluating user input using StringTokenizer while utilizing custom checked exceptions

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

compare an integer to a null value

I need to see if a text field has an empty value. I need to see if
if(Double.parseDouble(distanceTf.getText())==0)
I know 0 won't work. I also know null won't work and I know .equals won't work.
Does anyone know how I can compare this line of code to a null value?
if (stageTf.getText().equals("") || Double.parseDouble(distanceTf.getText()) == null) {
JOptionPane.showMessageDialog(null, "You did not enter both a stage number and distance");
return;
}
Thanks for all the above replies but they don't work.
The part of the code I have trouble with is:
if (Double.parseDouble(distanceTf.getText())==null)
The rest of it is fine.
I have tried putting this outside the if statement and using distanceTf.getText().equals("")
in the if statement but this doesn't work either.
I just can't find out how to assign an empty value to the line of code for a double.
I know null, .equals or "" won't work.
You're not clear on which value could be null, so I'll assume both.
Since Double.parseDouble requires a non-null argument, you need to check it for null.
if(null != distanceTf.getText() && Double.parseDouble(distanceTf.getText()) != 0.0)
stageTf.getText() could return null too, but if you're guaranteed to be comparing a known non-null String against null, it would return false. So, this comparison is safer:
if("".equals(stageTf.getText())
The important thing to understand is: what you mean with null value? A null reference or an empty string?
You could do
stageTf.getText().isEmpty()
to check if the string is empty and parse it only if it contains something.
// here remember it's still wrong
if (!stageTf.getText().isEmpty() && Double.parseDouble(distanceTf.getText()) == null) {
Second problem: Double.parseDouble doesn't return null since it returns a native type.. it thrown an exception if something went wrong. So you can catch NumberFormatException.
Then you could write:
try {
double result;
if (!stageTf.getText().isEmpty() && (result = Double.parseDouble(distanceTf.getText()))) {
/* i think you need the result of the conversion, so i saved it in result */
}
}
catch (NumberFormatException e) { /* something went wrong! */ }
You need to test if the field is empty first. You did it correctly with your first conditional on the stageTf field. You need to do the same with the distanceTF field. This means nesting your conditional statements.
if(stageTF.getText().equals(""))
if(distanceTF.getText().equals("")){
/* ... */
} else {
//here it is safe to test for exceptions by using a try/catch
try{
//here you can parse the string to your Double
}catch(NumberFormatException nfe){ /* ... */ }
}
first of all you should check for null before empty because if the value is null you'll get a NullPointerException on the first one.
Second you'll get a NullPointerException if distanceTf.getText() is null on the Double.parseDouble
Double.parseDouble() doc
what I would do is create a method validate as follows:
private boolean validate(String field){ //where field = stageIf.getText() for example
if(field != null && field.trim().length() > 0)
return true;
else return false;
}
Parse outside if statment, then just compare :
if(distanceTf.getText() == "")

Why do I receive the error "This method must return a result of type ..."?

Can anyone see why I would receive the error "This method must return a result of type Card", when I clearly returns that variable "card" which is of type Card?
public Card playCard(int id){
int i = 0;
for (Card element : hand){
if (i <= hand.size())
{
if (element.getID() == id)
{
Card card = hand.get(i);
hand.remove(i);
return card;
}
else
{
i++;
}
}
else
{
throw new NullPointerException("Card does not exist in hand");
}
}
}
Your method doesn't return anything except in one possible scenario. It has to return something (or throw an exception) in all possible scenarios.
I think you meant to do this:
public Card playCard(int id){
for (Card element : hand) {
if (element.getID() == id) {
return element;
}
}
throw new SomeAppropriateException("Card does not exist in hand");
}
...but I'm guessing a bit (as I don't know what hand is, but it looked a lot like a List). That code will always either execute the return statement or throw an exception, there's no way to get to the end of the method without one of those things happening.
Note that throwing a NullPointerException for a condition that isn't caused by a null pointer is a Bad Idea(tm). (It's also best to be consistent in where you put your { and }.)
As hinted at by Tarlen, your code would need to be modified as such:
public Card playCard(int id){
int i = 0;
for (Card element : hand){
if (i <= hand.size())
{
if (element.getID() == id)
{
Card card = hand.get(i);
hand.remove(i);
return card;
}
else
{
i++;
}
}
else
{
throw new NullPointerException("Card does not exist in hand");
}
}
return null;
}
I believe that will account for all of the possible routes your program will need to take. You always gotta keep track of returning something EVERYWHERE the method can exit. If it can exit without hitting a return statement, you'll see that error.
Your method signature is:
public Card playCard(int id){
which means you must return a Card object. Your code only has one return statement, but there are many paths through the code. You must return a Card object for each path
It is because if hand is empty, then no value is being returned.
Add a return or a throw after your for loop.
You need to have a default return statement (or exception/error) for the whole method or at least one return statement (or exception/error) for every possible execution path in your code. As it is right now you have neither of them.

Logical mistake or not?

I have written this function which will set
val=max or min (if val comes null)
or val=val (val comes as an Integer or "max" or "min")
while calling i am probably sending checkValue(val,"min") or checkValue(val,"max")
public String checkValue(String val,String valType)
{
System.out.println("outside if val="+val);
if(!val.equals("min") && !val.equals("max"))
{
System.out.println("Inside if val="+val);
try{
System.out.println("*Inside try val="+val);
Integer.parseInt(val);
}
catch(NumberFormatException nFE)
{
System.out.println("***In catch val="+val);
val=valType;
}
return val;
}
else
{
return val;
}
}
But the problem is if val comes null then
outside if******val=null
is shown.
Can any1 tell me is this a logical mistake?
And why will I correct?
If val is null, then the expression val.equals("min") will throw an exception.
You could correct this by using:
if (!"min".equals(val) && !"max".equals(val))
to let it go inside the if block... but I would personally handle it at the start of the method:
if (val == null) {
// Do whatever you want
}
Btw, for the sake of readability you might want to consider allowing a little more whitespace in your code... at the moment it's very dense, which makes it harder to read.
...the problem is if val comes null then outside if****val=null is shown. Can any1 tell me is this a logical mistake?
The output is correct; whether you want it to come out that way is up to you.
Your next line
if(!val.equals("min") && !val.equals("max")){
...will throw a NullPointerException because you're trying to dereference val, which is null. You'll want to add an explicit check for whether val is null:
if (val == null) {
// Do what you want to do when val == null
}
you should use valType instead of val to check either minimum or maximum is necessary to check.
My advice to you in such cases to use boolean value or enum instead of strings. Consider something like that:
/**
* check the value for minimum if min is true and for maximum otherwise
*/
public String checkValue(String val, boolean min){
if (min) {
// ...
} else {
// ...
}
}
If you need to compare strings against constants you should write it the other way around to make it null-safe:
if (! "min".equals(val))
And while this is mostly a style issue, I would make all method arguments final and not re-assign them (because that is confusing), and you can also return from within the method, not just at the end. Or if you want to return at the end, do it at the very end, not have the same return statement in both the if and the else branch.

Categories

Resources