Custom exceptions not working - java

I am trying to create two exceptions, one that is thrown when the month number is greater than 12 or less than 1, and another that is thrown when the month name is invalid. I thought that I included all the necessary steps ( I'm bad at exceptions ), but my main class is still not working. Any insight as to what I did wrong?
public class Month {
private int monthNumber;
/**
* Creates a new month set to January
*/
public Month(){
monthNumber = 1;
}
/**
* Creates a month set to the month number provided by the user
* #param m the number of the month
*/
public Month(int m) throws MonthsNumberException{
if (m<1 || m>12){
throw new MonthsNumberException("Number has to be greater than 1 and less than 12");
}else{
monthNumber = m;
}
}
/**
* Creates a month based on the string name provided
* #param m String values for the name of the month
*/
public Month(String m) throws MonthsNameException{
switch(m){
case "January":
monthNumber = 1;
break;
case "February":
monthNumber = 2;
break;
case "March":
monthNumber = 3;
break;
case "April":
monthNumber = 4;
break;
case "May":
monthNumber = 5;
break;
case "June":
monthNumber = 6;
break;
case "July":
monthNumber = 7;
break;
case "August":
monthNumber = 8;
break;
case "September":
monthNumber = 9;
break;
case "October":
monthNumber = 10;
break;
case "November":
monthNumber = 11;
break;
case "December":
monthNumber = 12;
break;
default:
throw new MonthsNameException("Invalid month name: " + m);
}
}
/**
* changes the month to the number provided
* #param m the number of the month
*/
public void setMonthNumber(int m) throws MonthsNumberException{
if (m<1 || m>12){
throw new MonthsNumberException("Number has to be greater than 1 and less than 12");
}else{
monthNumber = m;
}
}
/**
* returns the number of the month
* #return the number of the month
*/
public int getMonthNumber(){
return monthNumber;
}
/**
* returns the name of the month
* #return the name of the month
*/
public String getMonthName(){
String month="";
switch(monthNumber){
case 1:
month = "January";
break;
case 2:
month = "February";
break;
case 3:
month = "March";
break;
case 4:
month = "April";
break;
case 5:
month = "May";
break;
case 6:
month = "June";
break;
case 7:
month = "July";
break;
case 8:
month = "August";
break;
case 9:
month = "September";
break;
case 10:
month = "October";
break;
case 11:
month = "November";
break;
case 12:
month = "December";
break;
}
return month;
}
/**
* returns a string representation of the month
* #return the name of the month
*/
public String toString(){
return getMonthName();
}
/**
* if the two items are the same returns true
* #param m the month object to compare
* #return true if they are the same, false if not
*/
public boolean equals(Month m){
if (m.getMonthNumber() == this.getMonthNumber()){
return true;
}else{
return false;
}
}
/**
* If this calling item is after the month object passed as argument returns true
* #param m the month object
* #return true if calling object greater, false of argument greater
*/
public boolean greaterThan(Month m){
if (this.getMonthNumber()>m.getMonthNumber()){
return true;
}else{
return false;
}
}
/**
* If this calling item is before the month object passed as argument returns true
* #param m the month object
* #return true if calling object less than, false of argument less than
*/
public boolean lessThan(Month m){
if (this.getMonthNumber()<m.getMonthNumber()){
return true;
}else{
return false;
}
}
class MonthsNumberException extends Exception
{
public MonthsNumberException(String message)
{
super(message);
}
}
class MonthsNameException extends Exception
{
public MonthsNameException(String message)
{
super(message);
}
}
}
import javax.swing.*;
public class MonthDemo {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
String response = JOptionPane.showInputDialog(null, "Please enter a month number");
int mNumber = Integer.parseInt(response);
Month m1 = new Month(mNumber);
JOptionPane.showMessageDialog(null, m1.toString());
response = JOptionPane.showInputDialog(null, "Please enter a month name");
Month m2 = new Month(response);
JOptionPane.showMessageDialog(null, m2.toString());
}
}

Problem #1: You have to throw exceptions where Month is changed.
Problem #2: You are not allowed to catch the exception in the Main
method.
After fully understanding your homework I have a shortened solution for you. When you extend Exception this is called a "checked" Exception which means you HAVE to surround it in a try catch, but if you extend RuntimeException(also Error) it will allow you to execute the method in the Main thread without handling it. The consequence of this is your program will shutdown if the Exception is thrown, but that seems to be the desired result of your homework. Take your code as it is in your original question and just change this.
#SuppressWarnings("serial")
class MonthsNumberException extends RuntimeException {
public MonthsNumberException(String message) {
super(message);
}
}
#SuppressWarnings("serial")
class MonthsNameException extends RuntimeException {
public MonthsNameException(String message) {
super(message);
}
}
This should resolve your homework problem.

Haven't tried your code, and as you haven't told us the exact error, I am simply guessing here.
You have mentioned that the line Month m2 = new Month(response); is having problem.
Month(int) constructor is throwing a checked exception. However, your main method, which is the caller of this constructor, is not doing any proper handling. You should either catch it, or declare your main method to throws MonthsNumberException.
And please, don't simply throw out a big piece of code and "ask" question like this. There are lot of things you should do:
Have a simplified program to verify your understanding, and to demonstrate your problem. How is the lessThan method relates to the problem? You should remove all those "noise" from your question so that people can stay focus in your problem
You should give enough information. If there is an error, tell us the error message, or symptoms of the problem. Just throw out a big piece of code is not helping.

Related

How to make a user re-input data if input does not equal a case in the switch?

I recently learned Java and I have a switch statement that gets user input from another class and i was wondering how to make the default case for my switch statement make the user re-input data.
Currently I have the following basic code
static int getMonthInt(String monthName)
{
switch(monthName.trim())
{
case "January":
return 1;
case "Febuary":
return 2;
case "March":
return 3;
case "April":
return 4;
case "May":
return 5;
case "June":
return 6;
case "July":
return 7;
case "August":
return 8;
case "September":
return 9;
case "October":
return 10;
case "November":
return 11;
case "December":
return 12;
default:
// what do i put here
}
}
I get user input from an input class called from another class like so:
public static void main(String[] args) {
String monthName;
int dayNumber;
int yearNumber;
monthName = Input.getString("Please enter the current month name with a capital letter!");
dayNumber = Input.getInt("Please enter the current day!");
yearNumber = Input.getInt("Please enter the current year!"); }
This all works. My problem is however that if someone enters an invalid input such as 'ovtomber' I want the user to be re-prompted to enter data. Would I put this in the default case of the switch or in the main method (where I get user input) also how would i do this (I tried both ways and couldnt get the expected behavior & I could not find any topics on input validation)?
In your switch statement you have the default return an obviously invalid month (commonly -1):
default:
return -1;
Then in your logic, you can request clarification if the result is -1, eg:
int validatedMonth;
do
{
monthName = Input.getString("Please enter the current month name with a capital letter!");
validatedMonth = getMonthInt(monthName);
if(validatedMonth == -1)
System.out.println("Invalid month name, please try again");
} while (validatedMonth == -1);
(example code, I haven't checked it compiles)
Maybe you can return 0 in the default case.
And in the main function
while(getMonthInt(String monthName) ==0){
/*get user input here*/
}
Then it will make user to keep giving input if it is default

Dealing with days of the week

I'm trying to write a program that counts through days of the week when given a number. I want to write this without using Arrays., or enum types, just methods How can I do this? I also want to be able to set a day of the week as starting point.
Thanks
public static void main(String[] args);
{
int sunday, monday, tuesday, wednesday, thursday, friday, saturday;
int week;
int day;
System.out.println(" Day of the week is" + day);
public void count()
public void week()
public void printday()
public void nextday()
public void previousday()
I'm not the best at this, but I figure practice makes perfect
This should do your trick, if i correctly understood your question :)
/**
*
* #param startingDay - day of the week starting point ( need to be between 0-6 )
* #param noDays number of days to count
* #return result Day of the week
*/
private static WeekDays getWeekDay(int startingDay, int noDays){
int dayNr = noDays % 7;
int finalDayNr = (startingDay + dayNr) % 7;
return WeekDays.values()[finalDayNr];
}
private static enum WeekDays {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
And the version with no ENUM, however the Enum version is desirable... from any point of view you might think of.
/**
*
* #param startingDay
* - day of the week starting point ( need to be between 0-6 )
* #param noDays
* number of days to count
* #return result Day of the week
*/
private static String getWeekDay(int startingDay, int noDays) {
int dayNr = noDays % 7;
int finalDayNr = (startingDay + dayNr) % 7;
return getDay(finalDayNr);
}
private static String getDay(int dayNr) {
switch (dayNr) {
case 0:
return "SUNDAY";
case 1:
return "MONDAY";
case 2:
return "TUESDAY";
case 3:
return "WEDNESDAY";
case 4:
return "THURSDAY";
case 5:
return "FRIDAY";
case 6:
return "SATURDAY";
}
throw new IllegalArgumentException("Wrong input. Day nr must be between 0-6.");
}
Usage sample ( for any of the two approach ):
public static void main(String[] args) {
System.out.println(getWeekDay(0, 15));
System.out.println(getWeekDay(1, 15));
System.out.println(getWeekDay(5, 3));
}
This looks like homework, but if you are not going to use arrays of days, I guess you can use a switch statement with the days of the week.
This particular sample iterates from day 3 (0 being Monday) to day 14 included.
for (int i = 3; i < 15; i++) {
String s = null;
switch (i % 7) {
case 0: s = "Monday"; break;
case 1: s = "Tuesday"; break;
case 2: s = "Wednesday"; break;
case 3: s = "Thursday"; break;
case 4: s = "Friday"; break;
case 5: s = "Saturday"; break;
case 6: s = "Sunday"; break;
}
System.out.println(s);
}
public static void main(String[] args) {
int day = 1;
System.out.println(isWeek(day));
printday(day);
}
public static boolean isWeek(int day) {
// Sunday or Saturday
if (day == 1 || day == 7) {
return false;
}
return true;
}
public static void printday(int day) {
switch (day) {
case 1:
System.out.println("Sunday");
break;
case 2:
System.out.println("Monday");
break;
// Until Saturday
default:
break;
}
}
Bad code but without arrays or enums someting like that ?

How can i do input validations when user inputs values directly into objects?-JAVA

Is this possible to achieve or have i wrongly understood this question?
This is the question:
Implement a class MyDate that has integer data members to store month, day,
and year. The class should have a three-parameter constructor that allows the
date to be set at the time a new MyDate object is created. If the user creates a
MyDate object without passing any arguments, or if any of the values passed
are invalid, the default values of 1, 1, 2001 (i.e., January 1, 2001) should be
used. The class should have member functions to print the date in the following
formats:
3/15/10
March 15, 2010
15 March 2010
Demonstrate the usage of class MyDate by writing a class TestMyDate with a
main method that declares an object of type MyDate and displays it using all
the 3 formats.
Input Validation: Only accept values between 1 and 12 for the month, between
1 and 31 for the day, and between 1950 and 2020 for the year.
I've implemented this question but i can't seem to validate user input when the value is inserted at the time a new object is created. How can i do this? Please don't tell me to do research because i have done it. If Google could provide me with the answer i wouldn't have come here. Please help me.
Here's my codes:
The MyDate class:
package Number1;
public class MyDate {
private int month;
private int day;
private int year;
public MyDate()
{
month = 1;
day = 1;
year = 2001;
}
public MyDate(int m,int d,int y)
{
this.month = m;
this.day = d;
this.year = y;
}
public int getMonth()
{
return month;
}
public int getDay()
{
return day;
}
public int getYear()
{
return year;
}
public void Format1()
{
int m,d,y,afterM;
m = getMonth();
d = getDay();
y = getYear();
afterM = y % 100;
System.out.println(""+m+"/"+d+"/"+afterM);
}
public void Format2()
{
int m,d,y;
String word = null;
m = getMonth();
d = getDay();
y = getYear();
switch(m)
{
case 1:
{
word = "January";
break;
}
case 2:
{
word = "February";
break;
}
case 3:
{
word = "March";
break;
}
case 4:
{
word = "April";
break;
}
case 5:
{
word = "May";
break;
}
case 6:
{
word = "June";
break;
}
case 7:
{
word = "July";
break;
}
case 8:
{
word = "August";
break;
}
case 9:
{
word = "September";
break;
}
case 10:
{
word = "October";
break;
}
case 11:
{
word = "November";
break;
}
case 12:
{
word = "December";
break;
}
default:
{
System.out.println("Please enter a number between 1-12");
break;
}
}
System.out.println(""+word+" "+d+","+y);
}
public void Format3()
{
int m,d,y;
String word = null;
m = getMonth();
d = getDay();
y = getYear();
switch(m)
{
case 1:
{
word = "January";
break;
}
case 2:
{
word = "February";
break;
}
case 3:
{
word = "March";
break;
}
case 4:
{
word = "April";
break;
}
case 5:
{
word = "May";
break;
}
case 6:
{
word = "June";
break;
}
case 7:
{
word = "July";
break;
}
case 8:
{
word = "August";
break;
}
case 9:
{
word = "September";
break;
}
case 10:
{
word = "October";
break;
}
case 11:
{
word = "November";
break;
}
case 12:
{
word = "December";
break;
}
default:
{
System.out.println("Please enter a number between 1-12");
break;
}
}
System.out.println(""+d+" "+word+" "+y);
}
}
The main TestMyDate:
package Number1;
public class TestMyDate {
public static void main(String[] args) {
MyDate D = new MyDate(7,23,2013);
D.Format1();
System.out.println();
D.Format2();
System.out.println();
D.Format3();
}
}
These codes only returns the dates in these different formats. Thanks for trying to help.
I think you can do the validation and throw new IllegalArgumentException("illegal date") in MyDate() to make all the client code strictly conform the rule:
public MyDate(int m,int d,int y)
{
// do some validate here
if (!validate(m, d, y))
throw new IllegalArgumentException("illegal date")
this.month = m;
this.day = d;
this.year = y;
}
private boolean validate(int m, int d, int y){
// use here as the central place of your validation (Format1(), Format2(), Format3(), ...)
}
I suggest you
input the values you need to read
validate the inputs are you go.
only once you have valid data create the object.
I suggest you don't use a class to input it's own values. This is making the class overly complicated.
I also suggest you use arrays instead of long switch statements. You can replace your switch statements with two lines of code.
You need to run your validation in the constructor before assigning them to the member variables. Your best bet would be to create private methods that return a bool so you can reuse the logic in the event that you add setters to those properties.
public MyDate(int m, int d, int y)
{
if (monthIsValid(m)) {
this.month = m;
}
if (dayIsValid(d)) {
this.day = d;
}
if (yearIsValid(y)) {
this.year = y;
}
}
Having the switch statement is fine, though I'd only have it in a single place, and call it from both Format methods.

Unable to have the methods in one class completely run in main method when called by a class that extends first class

first class built. I think my problems lie within this first class. But i am unable to get the statement to print to the main program when method is called. I am new to java came from perl. Ive tried returning values associated with dmg and blk but the complier says they were never intitialized.
import java.util.Random;
/*****************************************************************************
* roll - rolls the dice. *
* getDice1 - returns value of dice one. *
* getDice2 - returns value of dice two. *
* getTotal - returns the sum value of both dice. *
* *
* *
*****************************************************************************/
//global variables for use throughout class.
public class Options {
int dice1;
int dice2;
int dmg;
int blk;
int health = 100;
Random randm = new Random();
public Options() {
roll();
Attack();
Block();
}
public void roll() {
dice1 = randm.nextInt(6)+1;
dice2 = randm.nextInt(6)+1;
}
public int getTotal() {
return dice1 + dice2;
}
//switch statement used to compare the value of the roll to the determined value of attack.
public protected Attack() {
dice1 = randm.nextInt(6)+1;
dice2 = randm.nextInt(6)+1;
getTotal();
int dmg;
switch (getTotal()) {
case 1: dmg = 2;
break;
case 2: dmg = 3;
break;
case 3: dmg = 4;
break;
case 4: dmg = 5;
break;
case 5: dmg = 6;
break;
case 6: dmg = 7;
break;
case 7: dmg = 8;
break;
case 8: dmg = 9;
break;
case 9: dmg = 10;
break;
case 10: dmg = 11;
break;
case 11: dmg = 12;
break;
}
}
// switch statement is used to compare the roll of dice to determine the value of blk.
public protected Block() {
dice1 = randm.nextInt(6)+1;
dice2 = randm.nextInt(6)+1;
getTotal();
int blk;
switch (getTotal()){
case 1: blk = 2;
break;
case 2: blk = 3;
break;
case 3: blk = 4;
break;
case 4: blk = 5;
break;
case 5: blk = 6;
break;
case 6: blk = 7;
break;
case 7: blk = 8;
break;
case 8: blk = 9;
break;
case 9: blk = 10;
break;
case 10: blk = 11;
break;
case 11: blk = 12;
break;
}
}
// determination whether or not the user has lost health or remains at current health.
public void setHealth(){
health = 100;
}
public int getHealth(){
if (dmg >= blk){
System.out.println("The attack hit for" + dmg);
return health - dmg;
}
else if (dmg < blk){
System.out.println("The attack was blocked");
return health;
}
return health;
}
}
then created character class to that i wanted to access the option methods.
public class Character extends Options {
String name;
public Character(String n) {
name = n;
}
public void setHealth(){
}
public int getHealth(){
return health;
}
public int Attack(){
return dmg;
}
public int Block(){
return blk;
}
}
Then final in the main program I dont believe the dice fro om options class are actually rolling a value because the print statements i put in the main are the only thing that print out. I even let it run for a full 30 mins last night without the sleep to just see if the logic kept coming up with more blocks vs attacks. but no dice it didnt complete at any point.
public class Game{
public static void main(String args[]){
//Constructor for the two separate characters.
Character monster = new Character("monster");
Character hero = new Character("hero");
monster.setHealth();
hero.setHealth();
System.out.println("Health has been set to 100.");
while (monster.getHealth() != 0 || hero.getHealth() !=0) {
try{
System.out.println("Monster is set to Attack!");
monster.Attack();
Thread.sleep(500);
System.out.println("Hero attempts to block");
hero.Block();
Thread.sleep(500);
System.out.println("Hero attempts to Attack");
hero.Attack();
Thread.sleep(500);
System.out.println("Monster attempts to Block");
monster.Block();
}
catch(Exception e){
System.out.println(e);
}
}
if (monster.getHealth() == 0) {
System.out.println("Hero defeated the monster!!!!");
}
else if (hero.getHealth() == 0 ){
System.out.println("Monster has defeated hero!!!!");
}
}
}
i had to use thread sleep as a way to make sure i wasnt missing if the lines from the options class were being missed in printing because the main program ran way to fast.
Attack() and Block() need return types and cannot be both public and protected.
There is already a Java class called Character. You should rename your class. In fact, your Character class is superfluous. The name attribute can be stored in the parent class and all the return statements can go in the parent methods.
Because you are overriding the Options Attack() and Block() methods in your Character class, the parent method is not being called; you need to call it using super.Attack() or super.Block(). But again, this child class is superfluous.
You shouldn't be calculating damage/health in the getHealth() method. Accessor methods should only be used for accessing attributes. Use the mutator method (setHealth()) for changing the value of health and doing your calculations.
Your call to getTotal() before your switch statement is unnecessary because you don't save the return value.
You really don't need those sleep calls.
The reason you think Options() is never initialized is because your Character constructor sets the name for your character, but it doesn't call the constructor for Options. So it never is initialized, or more specifically, all the values default to zero. (You'd want to call super();)
However, as #chancea said in a comment, there are actually a lot of errors in your code. Some quick things I'll mention:
-Options seems like you would want the dice to be re-rolled each time you want to Attack or Block, but it will be set just once when the object is created.
-You are calling getters such as hero.Attack() which just returns an int. You don't do anything with this call, you just get the value and then discard it.
-getHealth() is what is doing the damage to your character. It subtracts your character's health from its own attack and defense, with no regard to the opponent's attack or defense.

returning something not needed (for compiler)

In this code:
Can anyone explain me .. why we need to return "Error" ?
And in some integer methods (not in this code) .. why return 0 is used?
package chapter4;
import java.util.Scanner;
class DateThirdTry
{
private String month;
private int day;
private int year; //a four digit number.
public void setDate(int newMonth, int newDay, int newYear)
{
month = monthString(newMonth);
day = newDay;
year = newYear;
}
public void writeOutput()
{
System.out.println(month + " " + day + ", " + year);
}
public String monthString(int monthNumber)
{
switch (monthNumber)
{
case 1:
return "January";
case 2:
return "February";
case 3:
return "March";
case 4:
return "April";
case 5:
return "May";
case 6:
return "June";
case 7:
return "July";
case 8:
return "August";
case 9:
return "September";
case 10:
return "October";
case 11:
return "November";
case 12:
return "December";
default:
System.out.println("Fatal Error");
System.exit(0);
return "Error"; //to keep the compiler happy
}
}
}
class DateThirdTryDemo
{
public static void main(String[] args)
{
DateThirdTry date = new DateThirdTry( );
int year = 1882;
date.setDate(6, 17, year);
date.writeOutput( );
}
}
1) Java will give a compiler error if a function has an exit path that doesn't return a value. Not returning a value is illegal in Java. Arguably a Good Thing.
2) In this case, your function calls "System.exit()" instead of returning a value. You know the program isn't going to execute the 'return "Error"', but you need to add it to satisfy the compiler.
3) The appropriate thing to do, however, is to throw an exception.
It's easy, your method monthString() returns a... String:
public String monthString(int monthNumber)
So, you have to return a String, and not an int, so you can't return 0.
If your method was returning an int, you could return 0.
But, in your case, you should maybe throw an exception instead of returning "Error" and using System.exit() like that:
public String monthString(int monthNumber) throws IllegalArgumentException {
and throw it:
default:
System.out.println("Fatal Error");
throw new IllegalArgumentException("Incorrect month number");
Or even better, you can directly use what is provided by Java to implement your function:
public static String monthString(final int monthNumber) {
final Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, monthNumber-1);
return c.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.ENGLISH);
}

Categories

Resources