Issue creating and using my own exception class - java

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");
}

Related

How can I parameterize a generic method so as not to repeat the structure of the tests?

I have a Spring Boot project in which I am adding the below Test of some of the classes.
#Test
void documentException() {
assertThrows(DocumentException.class, () -> {
try {
throw new DocumentException();
} catch (Exception ex) {
assertEquals("Error converting document format", ex.getMessage());
assertEquals(417 /* EXPECTATION_FAILED */, ex.getHttpStatus());
assertEquals(ErrorCodes.DOCUMENT_ERROR, ex.getCode());
throw ex;
}
});
}
#Test
void maxUserException() {
assertThrows(MaxUserException.class, () -> {
try {
Integer maxUsers = 5;
throw new MaxUserException(maxUsers);
} catch (Exception ex) {
Integer maxUsers = 5;
assertEquals("Excedido el número máximo de "+ maxUsers +" dispositivos", ex.getMessage());
assertEquals(403 /* FORBIDDEN */, ex.getHttpStatus());
assertEquals(ErrorCodes.MAX_USERS_DEVICES, ex.getCode());
throw ex;
}
});
}
#Test
void docFormatException() {
assertThrows(DocFormatException.class, () -> {
try {
throw new DocFormatException();
} catch (Exception ex) {
assertEquals("Document format", ex.getMessage());
assertEquals(415 /* UNSUPPORTED_MEDIA_TYPE */, ex.getHttpStatus());
assertEquals(ErrorCodes.DOCUMENT_ERROR, ex.getCode());
throw ex;
}
});
}
For each class I use the same method.
Would there be any way to create a class with a #Test and call it for each class? So as not to have to create such a large structure for each of the classes.
What I want is to make a general method and apply it to each of the classes. So as not to have to repeat the same structure for all classes.
Well, answering directly to your question and using your actual examples - if you want to avoid code duplication then you can use some utility method.
Assuming your exceptions are subtypes of your custom class or implement the same interface which have methods getHttpStatus and getCode. Let's say parent class or interface has name CustomException.
Create a new class, for example TestUtils and define the method which can be reused is your tests, something like that (idk what type getCode() should return, so I assume it's String)
public class TestUtils {
public static void testException(CustomException exception, String message,
String errorCode, int httpStatus) {
assertThrows(exception.getClass(), () -> {
try {
throw exception;
} catch (CustomException ex) {
assertEquals(message, ex.getMessage());
assertEquals(httpStatus, ex.getHttpStatus());
assertEquals(errorCode, ex.getCode());
throw ex;
}
});
}
}
Then your test methods can be simplified:
#Test
void documentException() {
TestUtils.testException(new DocumentException(),
"Error converting document format",
417,
ErrorCodes.DOCUMENT_ERROR);
}
maxUserException() a bit trickier but still works:
#Test
void maxUserException() {
int maxUsers = 5;
MaxUserException exception = new MaxUserException(maxUsers);
String message = "Excedido el número máximo de "+ maxUsers +" dispositivos";
TestUtils.testException(exception, message, ErrorCodes.MAX_USERS_DEVICES, 403);
}
Hope it can be helpful. However it's worth mentioning - if it's your real test code and it's written exactly like this, then those methods attempt to test that your custom exceptions are created with correct default parameters (that's all) and in that case, test methods can be simplified as they are overcomplicated right now.
Your example test methods seems bit complicated, but it worth mentioning there in JUnit5 there are annotations to handle parameterized test.
You should look into these documents:
Java doc for #ParameterizedTest , #ValueSource , #CsvSource.
here is a sample example of how to parameterized a test:
#ParameterizedTest
#CsvSource(value = {
// input and expected output separated by :
"test:test",
"tEst:test",
"Java:java"
}, delimiter = ':')
void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) {
String actualValue = input.toLowerCase();
assertEquals(expected, actualValue);
}
Have a look in this Guide to JUnit 5 Parameterized Tests.

Issues with constants in static block java

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.

Loose control from constructor

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.

How can I customize custom exceptions in Java?

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.

Try Catch Block in Java

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.

Categories