I need to implement a try and catch around 2 blocks of code. each need there own. code that I have written. I have made a class for it:
public boolean makeOffer(int offer) throws OfferException
{
// reject offer if sale is not open for offers
if (this.acceptingOffers == false)
{
return false;
}
// reject offer if it is not higher than the current highest offer
else if (offer <= this.currentOffer)
{
throw new OfferException("Offer not High enough!");
}
else
{
// new offer is valid so update current highest offer
this.currentOffer = offer;
// check to see if reserve price has been reached or exceeded
if (this.currentOffer >= this.reservePrice)
{
// close the Sale if reserve has been met
this.acceptingOffers = false;
}
return true;
}
}
second blockis very similar to the first as this is in a separate class to the first.
public boolean makeOffer(int offer)
{
// reject offer if sale is not open for offers
if (this.acceptingOffers == false)
{
return false;
}
// reject offer if it is not higher than the current highest offer
else if (offer <= this.currentOffer)
{
return false;
}
else
{
// new offer is valid so update current highest offer
this.currentOffer = offer;
// check to see if reserve price has been reached or exceeded
if (this.currentOffer >= this.reservePrice)
{
System.out.println("Name of the Highest Bidder: ");
Scanner s = new Scanner(System.in);
this.highestBidder = s.nextLine();
s.close();
this.acceptingOffers = false;
}
return true;
}
When you use a method that throws an Exception you have to use the keywords throws (unless you throw a RuntimeException. These do not have to be declared this way). In this way, the other methods that call this method can handle the exception.
You can use something like this:
private static void submitOffer() throws OfferException{
// ...
if ( sales[i].getSaleID().equalsIgnoreCase(saleID)){
//try { Remove this try
offerAccepted = sales[i].makeOffer(offerPrice);
if (offerAccepted == true){
System.out.print("Offer was accepted");
if(offerPrice <= sales[i].getReservePrice()){
System.out.print("Reserve Price was met");
}else{
throw new OfferException("Resever not met!");
}
}else{
throw new OfferException("Offer was Not accepted");
}
//....
}
}
When you call the submitOffer() method you can use:
public void myMethod() throws OfferException{
MyClass.submitOffer();
}
or
public void myMethod(){
try{
MyClass.submitOffer();
} catch( OfferException oe){
//handle here the exception
}
}
Also if you are using a custom Exception you should call the super constructor.
public class OfferException extends Exception{
String message;
public OfferException(String message){
super(message); //call the super constructor
this.message = message; //Do you need it ?
}
}
Related
Is there a way to eliminate all the "if" statements from this class and still maintain the exact same functionality ?
So far I managed to simplify the code by creating the 2 extra functions: isNameValid and isPhoneValid, but I need a way to get rid of all the "if" statements.
public class ClientValidator implements Validator<Client> {
#Override
public void validate(Client entity) throws ValidatorException {
if(!isNameValid(entity.getName())){
throw new ClientException("Invalid name!");
}
if(!isPhoneValid(entity.getPhone())){
throw new ClientException("Invalid phone number!");
}
}
private boolean isNameValid(String name) {
return name.length() > 1 && name.length() < 100;
}
private boolean isPhoneValid(String phone) {
try {
Long.parseLong(phone);
} catch (NumberFormatException e) {
return false;
}
return true;
}
}
you can try optionals and do filtering on the methods, but you miss reason specific exceptions:
Optional
.of(entity)
.filter(entity -> isNameValid(entity.getName())
.filter(entity -> isPhoneValid(entity.getPhone())
.orElseThrow(() -> new ClientException("Wrong client data"));
Is there a way to eliminate all the "if" statements from this class and still maintain the exact same functionality ?
Yes. It's a hack, but if isn't the only flow-control. Easiest I see, a while loop with the same logic. Like,
#Override
public void validate(Client entity) throws ValidatorException {
while (!isNameValid(entity.getName())) {
throw new ClientException("Invalid name!");
}
while (!isPhoneValid(entity.getPhone())) {
throw new ClientException("Invalid phone number!");
}
}
You could also use switch statements like
#Override
public void validate(Client entity) throws ValidatorException {
switch (isNameValid(entity.getName())) {
case false:
throw new ClientException("Invalid name!");
}
switch (isPhoneValid(entity.getPhone())) {
case false:
throw new ClientException("Invalid phone number!");
}
}
What about this :
#Override
public void validate(String entity) throws ClientException {
String message = !isNameValid(entity.getName()) ? "Invalid name!"
: !isPhoneValid(entity.getPhone()) ? "Invalid phone number!" : "";
Stream.of(message).filter(m -> m.isEmpty()).findAny()
.orElseThrow(() -> new ClientException (message));
}
I could think of some dirty tricks like
public void validate(Client entity) throws ValidatorException {
try {
int len = entity.getName().length();
int isshort = 1 / len;
int islong = 1 / max (0, 100- length);
} catch (Exception e) {
throw new ClientException("Invalid name!");
}
try {
Long.parseLong(entity.getPhone());
} catch (NumberFormatException e) {
throw new ClientException("Invalid phone number!");
}
}
So no if needed
Instead of the try{}catch(Exception e){} method, is there a way to just state a custom message that replaces the exception message when exceptions like InputMismatchException, NoSuchElementException etc. occurs anywhere on the program?
EDIT: I want another method because if I use try{}catch(Exception e){} method than I will have to do it everywhere and the code also becomes longer.
For example:
public static String genderOutput()
{
try
{
System.out.print("\nMale - 1 \nFemale - 2 \n\nEnter either 1 or 2: ");
int genderInput = userInput.nextInt();
if(genderInput == 1)
{
String userGender = "Mr.";
return userGender;
}
else if(genderInput == 2)
{
String userGender = "Mrs.";
return userGender;
}
else
{
String userGender = " ";
return userGender;
}
}
catch (Exception e)
{
return null;
}
}
I have this function, now if there were multiple functions in a class like this then I would have to have the try{}catch(Exception e){} method everywhere. Wouldn't it be more efficient if you can just replace the exception message with your own and when such exception occurs which has a custom message stated to them then it would just throw out the custom message instead. This way, the code will be shorter as well.
SOLUTION TO MY PROBLEM:
public class Test
{
public static Scanner userInput = new Scanner(System.in);
public static String titleName = "TheRivalsRage";
public static String exitLevelMessage = "Program exited!";
public static String errorMessageTitle = "\n[Error] ";
public static String intInputMismatchException = "Please enter an Integer Value!";
public static String intNoSuchElementException = "Please enter either '1' or '2' without the quotes!";
public static String lineNoSuchElementException = "Please enter something!";
public static String bothIllegalStateException = "Scanner closed unexpectedly!";
public static void main(String[] args)
throws Exception
{
String usernameOutput;
String userGender;
try
{
System.out.print("Enter your username: ");
usernameOutput = userInput.nextLine();
userGender = genderOutput();
userInput.close();
}
catch(IllegalStateException e)
{
throw new IllegalStateException(errorMessageTitle + bothIllegalStateException);
}
if(userGender == null)
{
noSuchElementException();
}
else
{
System.out.println("\nWelcome " + userGender + " " + usernameOutput + " to " + titleName);
}
}
public static String genderOutput()
{
String userGender;
int genderInput;
System.out.print("\nMale - 1 \nFemale - 2 \n\nEnter either 1 or 2: ");
try
{
genderInput = userInput.nextInt();
}
catch(InputMismatchException e)
{
genderInput = 0;
inputMismatchException();
}
if(genderInput == 1)
{
userGender = "Mr.";
}
else if(genderInput == 2)
{
userGender = "Mrs.";
}
else
{
userGender = null;
}
return userGender;
}
public static void inputMismatchException()
throws InputMismatchException
{
throw new InputMismatchException(errorMessageTitle + intInputMismatchException);
}
public static void noSuchElementException()
throws NoSuchElementException
{
throw new NoSuchElementException(errorMessageTitle + intNoSuchElementException);
}
}
don't handle exception in each and every method just use throws Exception after method signature and handle it at end where the methods are being called.
and there in catch block you can throw your custom exception.
void method1() throws Exception{
//
}
void method2() throws Exception{
//
}
void finalmethod(){
try{
method1();
method2();
}catch(InputMismatchException e){
throw customExcpetion("custommessage1");
}catch(Exception e){
throw customExcpetion("custommessage2");
}
}
You need a try/catch.
However, you do not need to catch all exceptions separately, because the exceptions that you mention are all subclasses of RuntimeException. Hence, it is sufficient to make a single try/catch in your main to intercept RuntimeException, and print the replacement message:
public static void main(String[] args) {
try {
... // Actual code
} catch (RuntimeException ex) {
System.err.println("A runtime error has occurred.");
}
}
You can try Aspectj or Spring aop by creating around advice. You can replace message by catching exception inside advice and rethrow.
Check http://howtodoinjava.com/spring/spring-aop/aspectj-around-advice-example/
To know about how to use spring aop for anound advice
Java doesn't provide this feature out of the box but nobody prevents you to create a class that composes a Scanner object and that decorates methods that you are using as nextInt().
Inside the decorated method, invoke nextInt(), catch the exception that it may throw and handle it by returning null as in your question.
If it makes sense, you could even provide a nextInt() method with a default value as parameter if the input fails.
public class MyCustomScanner{
private Scanner scanner;
...
public Integer nextInt(){
try{
return scanner.nextInt()
}
catch(InputMismatchException e){
myStateObj.setErrorMessage("....");
return null;
}
}
public Integer nextInt(Integer defaultValue){
try{
return scanner.nextInt()
}
catch(InputMismatchException e){
myStateObj.setErrorMessage("....");
return defaultValue;
}
}
}
Now you can use the class in this way :
MyCustomScanner scanner = new MyCustomScanner();
Integer intValue = scanner.nextInt();
Integer otherIntValue = scanner.nextInt(Integer.valueOf(4));
In my Java program, I have a class called Car, which is Serializable. I have another class called StaffCar which is a subclass of Car.
Then there a class called Fleet which essentially stores StaffCar objects in ArrayList<StaffCar> fleet.
I then have a class Main which consists of the main method which consists of a menu and a switch to handle menu options.
The problem I'm having is when I add a method in StaffCar, even if the method has nothing inside and the method isn't even called, one of the menu options which is 'Display all car information', stops working.
If I comment out this method, it starts working again.
The 'Display...' option calls printCars()from Fleet which has fleet loaded with StaffCar objects from the serialized file, it's like the existence of this method stops the file from even being read.
Snippet of Car
import java.util.ArrayList;
import java.io.*;
#SuppressWarnings("serial")
public class Car implements Serializable
{
//attributes for Car
String regNo;
String model;
int mileage;
//default constructor
public Car() throws CarException
{
try
{
setRegNo("??????");
setModel("Unknown");
setMileage(0);
}
catch (CarException c)
{
System.out.println(c.getMessage());
}
}
//setters
public void setRegNo(String regNo) throws CarException
{
if (regNo.isEmpty())
{
throw new CarException("\nInvalid registration number!\n");
}
this.regNo = regNo;
}
public void setModel(String model) throws CarException
{
if (model.isEmpty())
{
throw new CarException("\nModel can't be empty!\n");
}
this.model = model;
}
public void setMileage(int mileage) throws CarException
{
if (mileage < 0)
{
throw new CarException("\nInvalid mileage!");
}
this.mileage = mileage;
}
}
Snippet of StaffCar, where the problem is being caused
import java.util.ArrayList;
#SuppressWarnings("serial")
public class StaffCar extends Car
{
String staffName;
String availability;
public StaffCar() throws CarException
{
super();
try
{
setAvailability("Available");
setStaffName("");
}
catch (CarException c)
{
System.out.println(c.getMessage());
}
}
public void setStaffName(String staffName)
{
this.staffName = staffName;
}
public void setAvailability(String availability) throws CarException
{
if (availability != "Available" && availability != "Borrowed")
{
throw new CarException("\nInvalid borrow status!\n");
}
this.availability = availability;
}
//this method causing issues, even if empty
/*public void returnCar()
{
}*/
}
Snippet of Fleet class
import java.util.ArrayList;
import java.io.*;
public class Fleet
{
//declare container
ArrayList<StaffCar> fleet;
//container to hold regNos
ArrayList<String> regNumbers;
//create constructor
public Fleet()
{
fleet = new ArrayList<StaffCar>();
regNumbers = new ArrayList<String>();
}
//add method
public void addCar(StaffCar car)
{
fleet.add(car);
regNumbers.add(car.regNo);
}
//print all cars' details
public void printCars()
{
for (StaffCar car:fleet)
{
System.out.println(car);
}
}
public void saveAs(String fileName) throws CarException
{
FileOutputStream outputFile;
try
{
outputFile = new FileOutputStream(fileName);
}
catch (IOException io)
{
throw new CarException("\nCannot create " + fileName + "\n");
}
ObjectOutputStream fleetFile;
try
{
fleetFile = new ObjectOutputStream(outputFile);
fleetFile.writeObject(regNumbers);
fleetFile.writeObject(fleet);
fleetFile.close();
}
catch (FileNotFoundException e)
{
throw new CarException("\nCannot create " + fileName + "\n");
}
catch (IOException io)
{
throw new CarException("\nCannot write " + fileName + "\n");
}
}
#SuppressWarnings({ "unchecked", "resource" })
public void open(String fileName) throws CarException
{
FileInputStream inputFile;
try
{
inputFile = new FileInputStream(fileName);
}
catch (FileNotFoundException e)
{
throw new CarException("\nCannot open " + fileName + "\n");
}
ObjectInputStream fleetFile;
try
{
fleetFile = new ObjectInputStream(inputFile);
regNumbers = (ArrayList<String>)fleetFile.readObject();
fleet = (ArrayList<StaffCar>)fleetFile.readObject();
}
catch (IOException io)
{
throw new CarException("\nError reading from " + fileName + "\n");
}
catch (ClassNotFoundException e)
{
throw new CarException("\nError reading from " + fileName + "\n");
}
try
{
fleetFile.close();
}
catch (IOException io)
{
throw new CarException("\nCannot close " + fileName + "\n");
}
}
}
I apologise for what seems like me dumping a bunch of code to you, I know this is bad practice and I have tried to condense the code as much as I can, but I feel like this is all the relevant code to my problem.
Like I said, I don't understand why the simple addition of an empty method is causing this issue.
EDIT
Main class
public class Main
{
// new container
static Fleet fleet = new Fleet();
// initialise car object
static StaffCar car;
// programme loop variable
static boolean state = false;
String fileName;
public static void main(String[] args) throws CarException
{
start();
// programme loop
while (!state)
{
try
{
// menu option variable
String option;
//displays menu to user and takes in input
option = Console.askString("Menu:\n1 Add a car\n2 Display all car information\n3 Find a car\n4 Borrow a car\n5 Return a car\n6 Exit\n\n");
//removes white spaces
option = option.trim();
//switch to handle user request
switch (option)
{
//if option 1
case "1":
//call static add car method
addMethod();
break;
//if option 2
case "2":
//call static print car method
displayMethod();
break;
//..option 3
case "3":
//call static find car method
findMethod();
break;
//..option 4
case "4":
borrowMethod();
break;
case "5":
//returnMethod();
break;
case "6":
//call static quit method
quitMethod();
break;
default:
System.out.println();
System.out.println("Invalid option.");
System.out.println();
break;
}
}
catch (CarException c)
{
System.out.println(c.getMessage());
}
}
}
public static void start()
{
try
{
fleet.open("fleet.uwl");
}
catch (CarException e)
{
//System.out.println("\nFile not created yet!\n");
}
}
//static menu method to print cars
public static void displayMethod() throws CarException
{
System.out.println();
//call printCars method
fleet.printCars();
System.out.println();
}
}
You saved instances of StaffCar using serialization, then changed the StaffCar class, and are unable to read the saved StaffCar again.
That's because, if you don't specify a serialVersionUID in your class, the JVM computes one for you, based on the layout of the class (fields, methods, etc.). So, to temporarily fix your problem, examine the IOException thrown when reading the file, which should tell you what the serialVersionUID of the saved classes are, and add the following to your class:
private static final long serialVersionUID = XXXL;
where XXX is the serial version UID in the saved objects, which should be mentioned in the exception stack trace.
But really, you have these problems because you chose to use serialization for long term storage, which makes your code very hard to evolve. I wouldn't do that. Instead, I would choose a less fragile and easier to evolve format such as JSON or XML. Define what the file should contain, and generate a JSON/XML document containing this data. Then, whatever your future casses look like, as long as you still can parse JSON/XML, you'll be able to read the files and get the saved data.
I would like to block a Card in my abstract ATM.
At this manner, I need to interrupt the program if the PIN wasn't accepted after the third attempt so that the Main class won't execute the next Methods.
Is it System.exit(0) the optimal decision? I chose this one because it's simple, but I'm not sure.
public boolean authenticity(int tries) {
if (tries <= 3)
{
short pin = sc.nextShort();
if (pin == 1234) {
System.out.println("PIN is correct");
System.out.println("Card is active for operation!");
return true;
} else {
System.out.println("PIN isn't correct! You used " + tries +" attempt!");
return authenticity(++tries);
}
}
System.out.println("\nCard was blocked!");
System.exit(0);
return false;
}
class Main looks so:
public class Main {
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
ATM atm = new ATM();
MasterCard aeroflotCard = new MasterCard();
atm.initCard(aeroflotCard);
aeroflotCard.authenticity(1); // if pin is wrong, than you are looser:)
System.out.println("\nRefill your balance:");
aeroflotCard.add(sc.nextInt());
aeroflotCard.balance();
}
You may try the following piece of code:
public boolean authenticity(int tries) throws yourException {
if (tries <= 3) {
// ...
} else {
throw new yourException("\nCard was blocked!");
}
}
In the main method:
public static void main(String[] args) {
try {
aeroflotCard.authenticity(1);
System.out.println("\nRefill your balance:");
aeroflotCard.add(sc.nextInt());
aeroflotCard.balance();
} catch (yourException e) {
System.err.println(e.getMessage());
}
}
In the yourException class:
public class yourException extends Exception {
// here you can override needed methods
}
I have a FileUtils class that I would like to call that does some validation, and if it's wrong, it needs to return a good error message as to why the validation failed. So I have:
public static boolean isValidFile(File file) throws Exception
{
if(something)
throw new Exception("Something is wrong");
if(somethingElse)
throw new Exception("Something else is wrong");
if(whatever)
throw new Exception("Whatever is wrong");
return true;
}
public void anotherMethod()
{
try
{
if(isValidFile(file))
doSomething();
} catch (Exception e) {
displayErrorMessage(e.getMessage());
}
}
But this just seems odd to me because the isValidFile call can never be false. Also if I reverse the order of the if condition to do a quick boot out of the code if it's false, it's even weirder looking. Plus I don't like having exception handling code as a way of passing an error message.
public void anotherMethod()
{
try
{
if(!isValidFile(file))
return;
doSomething();
..
doMoreThings();
} catch (Exception e) {
displayErrorMessage(e.getMessage());
}
}
Is there a way to do all this without using Exceptions to and still be able to have the isValidFile() method return an indication of what the error is without returning an int with an error code like you see in C, etc.
You can e.g. change your method to
public static List<String> isValidFile(File file)
When the file is valid return an empty list or null,
otherwise return a list with the validation problems. The
return value is your indication if validation failed or not.
You could do something like this:
public static String validateFile(File file)
{
String ret = null;
if(something) {
ret = "Something is wrong";
} else if(somethingElse) {
ret = "Something else is wrong";
} else if(whatever) {
ret ="Whatever is wrong";
}
return ret;
}
public void anotherMethod()
{
String errorMessage = validateFile(file);
boolean fileIsValid = errorMessage == null;
if (fileIsValid) {
doSomething();
} else {
displayErrorMessage(errorMessage);
}
}
Not really pretty, but it gets the job done.