So I'm given this code and I have to create an Exception and then use a Try/Catch Block to catch it. I've already made the Exception, at the bottom of the code. But I've never used a Try/Catch Block before and am not sure how to implement it.
The Exception is if a rank that isn't listed under the enum is entered. I need to use a toString with the caught exception as well, but I'm pretty sure I can figure that one out.
package pracapp4;
import java.util.Scanner;
public class Staff extends Employee
{
enum Title
{
DEPARTMENT_HEAD, DIRECTOR, DEAN, VICE_CHANCELLOR, CHANCELLOR
}
private Title title;
public Staff()
{
super();
title = Title.DEPARTMENT_HEAD;
}
public Staff(String firstName, String lastName, int salary, Title title)
{
super(firstName, lastName, salary);
this.title = title;
}
#Override
public String toString()
{
return super.toString() + "\n\tTitle: " + title;
}
#Override
public void display()
{
System.out.println("<<Staff>>" + this);
}
#Override
public void input(Scanner in)
{
super.input(in);
if (in.hasNext())
{
this.title = Enum.valueOf(Title.class, in.next());
}
}
class InvalidRankException extends Exception
{
public InvalidRankException()
{
super ("Unknown Rank Name: ");
}
}
}
You don't need that exception. The moment you add your Title enum as the type you pass into the Staff constructor it's impossible to provide a value that's not in the enum. You'll never get an invalid title. That's the whole point of enum.
UPDATE: A little code review is an order here.
Your default constructor is rather odd. You can be department head without a name or salary? A call to "this" is appropriate here, and better default values are in order.
Whole numbers only for salary - OK. No units? USD? Euro?
Can salary be negative? Does that make sense? (Note to self: Don't work there.)
Why do you need both toString and display? What is display overriding? I'd recommend ditching display and sticking with toString.
Your input method makes no sense whatsoever.
Why is that Exception an inner class?
try/catch are used to catch exceptions thrown by methods inside the try clause. If the methods inside the try does not throw any exceptions then the try/catch will not makes sense.
Right now you made your exception but there is no method that throws your exception.
This is simple example on how to use exceptions:
public class myTest
{
public void myMethod() throws InvalidRankException
{
//Logic here
if(something_is_wrong)
{
throw new InvalidRankException("Invalid Rank on myMethod due ...");
}
}
class InvalidRankException extends Exception
{
public InvalidRankException()
{
super ("Unknown Rank Name: ");
}
}
Now, whenever you run MyTest.myMethod() the compiler will require a try/catch surrounding that call.
MyTest test = new MyTest();
try
{
test.myMethod();
}
catch(InvalidRankException ex)
{
//Something went wrong
}
Not exactly sure what you're trying to do, but try-catch blocks work like this:
try{
throw new Exception("Example exception");
}
catch(Exception e){
System.out.println( "Exception caught: " + e.getMessage() );
}
You'll also have to modify the method that you are trying so that it throws the Exception you're looking for:
public void doSomething(String blah) throws Exception
Catching an exception is as simple as:
try{
//Some code that throws MyExceptionClass
}catch(MyException e){
//Some code that handles the exception e
}
Throwing an exception is as simple as:
throw new MyException(some, parameters, of, your choice);
If your exception doesn't descend from RuntimeException then you must declare the the method throws it:
public void myExceptionCausingMethod() throws MyException{
//Method code
}
The try/catch statement encloses some code and is used to handle errors and exceptions that might occur in that code.
public void input(Scanner in) throws InvalidRankException {
super.input(in);
if (in.hasNext()) {
try {
title = Enum.valueOf(Title.class, in.next());
} catch(InvalidRankException ire) {
//You've hit the exception, code in here how to handle the situation
}
}
}
There's two issues here:
Enum won't return an invalid rank/title
InvalidRankException doesn't test for anything to cause it to fire.
Related
I'm trying to write an if statement that both catches an exception and does not catch an exception, I have caught the exception but I cannot figure out how to make the condition true so that it does not catch the exception and returns the desired value. Here is the code:
Main
package QuestionEditor;
public class Main {
public Main() {
super();
}
public static void main(String[] args) {
Wolf wolfExample = new Wolf();
try {
Food vegFood = new Food("Spinach");
System.out.println("************Wolf Exception example************");
wolfExample.eat(vegFood);
//wolfExample.eat(vegFood);
} catch (Exception e) {
// TODO: Add catch code
e.printStackTrace();
}
System.out.println("************Wolf Non-Exception example************");
Food Meat = new Food("Steak");
System.out.println("Wolves eat " + wolfExample.eat(Meat));
}
}
Animal
package QuestionEditor;
abstract public class Animal
{
String name;
int age;
String noise;
abstract public void makeNoise();
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
abstract public Food eat(Food x) throws Exception;
}
package QuestionEditor;
public class Carnivore extends Animal
{
public Food eat(Food x) throws Exception
{
if (x instanceof Meat) {
return x;
} else {
throw new Exception("Carnivores only eat meat!");
}
}
public String toString(Food x) {
return x.toString();
}
public void makeNoise()
{
noise = null;
}
public String getNoise()
{
return noise;
}
}
Food
package QuestionEditor;
public class Food {
//field that stores the name of the food
public String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
}
Meat
package QuestionEditor;
public class Meat extends Food
{
public Meat(String name) {
super(name);
}
public String getName() {
return super.getName();
}
}
Wolf
package QuestionEditor;
public class Wolf extends Carnivore
{
Wolf()
{
name = "Alex";
age = 4;
}
public void makeNoise()
{
noise = "Woof!";
}
public String getNoise()
{
return noise;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public Food eat(Food x) throws Exception
{
if (x instanceof Meat) {
return x;
} else {
throw new Exception("Carnivores only eat meat!");
}
}
}
Output
************Wolf Exception example************
java.lang.Exception: Carnivores only eat meat!
************Wolf Non-Exception example************
at QuestionEditor.Wolf.eat(Wolf.java:34)
at QuestionEditor.Main.main(Main.java:15)
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - unreported exception java.lang.Exception; must be caught or declared to be thrown
at QuestionEditor.Main.main(Main.java:25)
C:\Users\lee-pc\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
It wants me to catch Meat as an exception but I want to make it so that Meat is not an exception and relates to the Meat condition in the if statement which looks like this:
public Food eat(Food x) throws Exception
{
if (x instanceof Meat) {
return x;
} else {
throw new Exception("Carnivores only eat meat!");
}
}
Should be true of this:
Food Meat = new Food("Steak");
System.out.println("Wolves eat " + wolfExample.eat(Meat));
The desired output would be:
************Wolf Exception example************
java.lang.Exception: Carnivores only eat meat!
************Wolf Non-Exception example************
Wolves eat Meat
I understand that I have made an error but I'm struggling to figure out how to resolve it, any help would be great, thanks.
The reason why you don't get "Wolves eat Meat" printed, but an Exception is that you still need a try - catch block around every call to .eat() even when you know that the Exception won't be thrown.
The exception you are getting here before the line is printed is a RuntimeException because the code is not compilable
The second reson why this is not working, is that the "meat" you are giving the wolf is of the type Food and not Meat:
Food meat = new Food("Steak"); // no matter what name you give the food, it is still of the class Food
These little changes will make it work:
Food meat = new Meat("Steak"); // you create a Meat object and store it in a Food variable (so to speak)
try{
System.out.println("Wolves eat " + wolfExample.eat(meat)); // must be surrounded by a try-catch block
}catch(Exception ex){
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); // better way to log the exception than ex.printStackTrace();
}
BTW: variables should start with a small letter (Food meat instead of Food Meat .. otherwise how do you know if Meat is the class or your variable? ;)
EDIT
another sidenote: your class Food should override the toString() method to be properly printable. Otherwise System.out.println(meat) will just end up in something like com.my.package.Meat#5113de03
If a method has the potential to throw a checked exception, this is declared in its signature. If you call a method that declares the potential to throw an exception, you must either provide a handler for that exception or declare that you, too, could throw it. The fact that you, as you're writing the exercise, happen to know that you should not get the exception in this case does not relieve you of this requirement.
What you have to do is put the code that calls the method in a try block, and provide a catch block for the checked exception that the method declares it could throw (Exception in this case). This does not mean that the exception will get thrown - in this case it won't - but Java insists on knowing what it should do if it were thrown.
Some people - notably the Spring community - don't really like this behavior, so they use unchecked exceptions for just about everything. (Unchecked exceptions are those derived form RuntimeException or Error, though Error is generally reserved for more severe situations.) The original design of Java, though, was to ensure that every checked exception should eventually reach a handler.
I have two questions regarding the static block and Constants with below code.
Constant (or even simple Static variable) cannot be directly referrenced from static block. It gives error saying "Cannot reference a field before it is defined". But it is ok when accessing through a static method.
If I assign a value to a constant in static block's catch as mentioned below it gives error saying "The final field NAME may already have been assigned". But if asigning in catch it gives error saying "The blank final field NAME may not have been initialized".
I want to know why is it bahaving like this?
Code :
public class TestStaticblock {
static{
try {
// NAME = dummyStringValue() + NAME_APPENDER; // Cannot reference a field before it is defined
// NAME = dummyStringValue() + getNameAppender(); // This is OK
NAME = dummyStringValue();
} catch (Exception e) {
NAME = null; // The final field NAME may already have been assigned
}
}
private static String dummyStringValue() throws Exception{
return "dummy";
}
private static String getNameAppender() throws Exception{
return NAME_APPENDER;
}
private static final String NAME; // If I comment Catch it says "The blank final field NAME may not have been initialized"
private static String NAME_APPENDER = "appender";
}
You can only assign to NAME once (because it is final). Assign the result to a temporary variable, and then assign to NAME (and don't silently swallow Exceptions). Something like,
static {
String temp = null;
try {
temp = dummyStringValue();
} catch (Exception e) {
e.printStackTrace();
}
NAME = temp;
}
The reason you can't assign NAME the way your are currently is because the compiler performs static program analysis (specifically, the data-flow analysis) and that detects that there is a possible code path where NAME is not assigned. And because NAME is final, that is a compilation error.
You cannot use a static final field in a static block before it has been assigned, yet you can access it just by calling a method.
For example, this code prints null FOO:
public class Main {
static final String FOO;
static {
foo();
FOO = "FOOFOO".substring(0, 3);
foo();
}
static void foo() {
System.out.println(FOO);
}
public static void main(String[] args) {}
}
This is undeniably odd, but I guess it would have made the language considerably more complicated to make things such as this impossible.
As for your second question, this doesn't compile.
static{
try {
NAME = dummyStringValue();
} catch (Exception e) {
NAME = null; // The final field NAME may already have been assigned
}
}
This is also odd. If an exception is thrown it can only have occurred inside the method dummyStringValue(). Since you can't assign values to final fields inside a method, it is completely impossible for the NAME variable to have already been assigned in the catch block. Therefore there is no possible code path where NAME is not assigned. You'd think it ought to work in the same way as
static{
if (someCondition()) {
NAME = dummyStringValue();
} else {
NAME = null;
}
}
which compiles fine.
I guess the reason is again that it would have made the language much more complicated to allow this. There is no great benefit to allowing it as you can just use a method or a temp variable as indicated in the other answers. Exceptions just are more complicated than if statements - they can act almost like a goto. A good point was made by #ElliottFrisch in the comments. What about something like this:
static{
try {
NAME1 = dummyStringValue1();
NAME2 = dummyStringValue2();
} catch (Exception e) {
// Has NAME1 been assigned here?
}
}
Perhaps this would be of assistance to those looking for something similar.
There is a little-known feature of Java (discussed in JavaSpecialists Throwing Exceptions from Fields that if you wish to initialise a final instance variable (i.e. NOT a static) to the result of a method call that throws an exception then you can avoid the obvious error by adding a constructor that throws the exception.
Note that this solution only works for non-statics (not what you are observing).
public class TestStaticblock {
private final String NAME = dummyStringValue();
// Adding this removes the "unreported Exception" above.
public TestStaticblock() throws Exception {
}
private static String dummyStringValue() throws Exception {
return "dummy";
}
}
My strong personal preference is to use methods instead of static initializer blocks which initializer a single variable:
private static final String NAME = getName();
private static String getName() {
try {
return something();
} catch (Exception e) {
return null;
}
}
You don't get issues like the one you have described.
You can only calculate one field value, so you are not tempted to throw lots of things into the same block.
You can re-invoke a method to test it.
I have a JUnit test class, which I'm new to making. I also trying to learn how to make my own exception classes. I have been creating a BigInt class, and one of the constructors takes in Strings. This bit of code is looping through an array, and its supposed to be checking if the character at each position is an integer. Right now there is an error that says "Unreachable catch block for BigIntFormatException. This exception is never thrown from the try statement body" Any ideas for why?
String[] s = { " - - 1424", "+ + 14324", "a142432", "1432 3413",
"+242134.32421", "", " \n", "\t ++" };
for (int i = 0; i < s.length; i++) {
try {
BigInt b = new BigInt(s[i]);
assertFalse(true);
} catch (BigIntFormatException e) {
assertTrue(true);
}
}
So far this is what my BigIntFormatException class just looks like, so any help with this part would be appreciated too.
public class BigIntFormatException extends Exception {
public BigIntFormatException() {
super();
}
public BigIntFormatException(String message) {
super(message);
}
}
Simply put, this compilation failure is quite clear: neither the constructor to BigInt nor the assertion declare that they are going to throw BigIntFormatException.
Since Exception is the class of checked exceptions (meaning that you do have to wrap them in a try-catch block), you must declare them to be thrown in your constructor of BigInt.
Here's the way you would do that.
public BigInt(String str) throws BigIntFormatException {
// logic
}
You need to throw the exception in your BigInt class
if(/*error condition*/) {
throw new BigIntFormatException("your message");
}
I am trying to call a custom catch expression
String value1 = side1_tb.getText();
String value2 = side2_tb.getText();
String value3 = side3_tb.getText();
try
{
result_lbl.setText(
actual_triangle.Triangle(
Double.parseDouble(value1),
Double.parseDouble(value2),
Double.parseDouble(value3)));
}
catch (NumberFormatException exe)
{
}
So from the above code you can see that there are three textboxes values are being assigned to a string variables and then I implemented a try and catch method with 'Numberformatexception' but in the place of 'Numberformatexception' I want to implement a custom exception and this exception will be declared in another class lets call this class EXCEPTIONclass.java and in here I want to create an exception if String values are not being able to parse to double values, which I am trying to achieve in the above code.
Not really sure how to extend the exception class and then declare a new exception.
You could do it as follows:
public class MyCustomException extends Exception
{
// To keep compiler happy about Exception being serializable.
// Note: This should carry meaningful value when these exceptions are going
// to be serialized
public static final long serialVersionUID = 1L;
public MyCustomException(String message, Throwable t)
{
super(message, t);
}
// Other constructors of interest from the super classes.
}
In your catch block, you would wrap the NumberFormatException as follows:
catch (NumberFormatException nfe)
{
throw new MyCustomException("<Your message>", nfe);
}
Just create your exception class deriving it from Throwable ( for checked exception ) or RuntimeException ( if you like it to be unchecked ) and throw it from your catch clause.
This is the original exception code
public class NoValueForParametarException extends Exception {
private Exception nestedException;
private int errorCode;
public NoValueForParametarException(String message) {
super(message);
}
public NoValueForParametarException(Exception ex,String message) {
super(message);
this.nestedException = ex;
}
public NoValueForParametarException(String message, int errorCode) {
super(message);
this.setErrorCode(errorCode);
}
public Exception getNestedException() {
return this.nestedException;
}
public void setNestedException(Exception nestedException) {
this.nestedException = nestedException;
}
public int getErrorCode() {
return this.errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String toString() {
StringBuffer errorMsg = new StringBuffer();
errorMsg.append("[" + super.getMessage() + "]:");
errorMsg.append((this.nestedException != null) ? ("\n[Nested exception]:" + this.nestedException):"");
return errorMsg.toString();
}
}
and this is the new one
public class NoValueForParametarWebServiceException extends NoValueForParametarException {
public NoValueForParametarWebServiceException(String message) {
super(message);
}
public NoValueForParametarWebServiceException(Exception ex,String message) {
super(message);
this.setNestedException(ex);
}
public NoValueForParametarWebServiceException(String message, int errorCode) {
super(message);
this.setErrorCode(errorCode);
}
public String toString() {
StringBuffer errorMsg = new StringBuffer();
errorMsg.append(super.getMessage());
errorMsg.append((this.getNestedException() != null) ? ("\n[Nested exception]:" + this.getNestedException()):"");
return errorMsg.toString();
}
}
All I need is to change the part of the toString() method so instead of errorMsg.append("[" + super.getMessage() + "]:"); I have errorMsg.append(super.getMessage());. The problem appears when, in a method, the original is thrown because the catch block set to NoValueForParametarWebServiceException doesn't catch the original. I know I could catch the original and just re-throw the new one (which would also be satisfying), but I was wondering if there is another way.
EDIT: It seems what I need is unclear, so to be more clear:
The program throws NoValueForParametarException. I want to catch it but use the toString() method of NoValueForParametarWebServiceException (that is the sole reason of creating the new class) because I need the output format of the new version without changing the old.
I don't see any reason to subclass your first exception. Also, if you get rid of the nestedException instance variable and use java.lang.Throwable's cause instead, you don't have to mess with overriding toString and you can delete most of this code.
The problem appears when, in a method,
the original is thrown because the
catch block set to
'NoValueForParametarWebServiceException'
doesn't catch the original. I know I
could catch the original and just
re-throw the new one (which would also
be satisfying)
You don't need to re throw child exception.
Just catch parent exception in this case.
try{
//your code
}catch(NoValueForParametarException e){
//whatever handling you need to do. suppose you call toString() method
System.out.println(e.toString());
}
In above case catch block will be executed if any of your exceptions are thrown
(NoValueForParametarException or NoValueForParametarWebServiceException).
And depending upon which exception is thrown its toString() method will be called. (Simple inheritance rule) i.e.
NoValueForParametarException is
thrown toString defined in
NoValueForParametarException class
will be called for instance.
And if
NoValueForParametarWebServiceException
is thrown then overriden toString
method from
NoValueForParametarWebServiceException
will be called.
Some tutorials related to exceptions:
http://download.oracle.com/javase/tutorial/essential/exceptions/index.html
http://tutorials.jenkov.com/java-exception-handling/index.html
Hope this helps.