I use the following enum type:
enum Status {OK,TIMEOUT,EXCEPTION}
But now I want to store what exactly the Exception is. Unfortunately you cannot instantiate an enum type. What is the best way to make something like the following possible?
switch(status)
{
case(OK) {System.out.println("Everything OK!");break;}
case(TIMEOUT) {System.out.println("Timeout :-(");break;}
case(EXCEPTION) {System.out.println("We have an exception: "+status.exception);break;}
}
My ideas
-
Class with singletons
class Status { final Exception e; public final Status OK = new Status(null); public final Status TIMEOUT = new Status(null); public Status(Exception e) {this.e=e;} }
Then I could do:
if(status==Status.OK) {System.out.println("Everything OK!");}
else if(status==Status.TIMEOUT) {System.out.println("Timeout :-(");}
else {System.out.println("We have an exception: "+status.exception);}
2. Several Classes
class Status {}
class StatusOK extends Status {}
class StatusTimeout extends Status {}
class StatusException extends Status
{
final Exception e;
public StatusException(Exception e) {this.e=e;}
}
Then I would need a bunch of “instanceOf”-statements.
P.S.: OK it seems that I didn’t explain it clearly enough. In my program I answer requests and I store the status of the processing of those requests:
Map<Request,Status> request2Status;
Thus I cannot use something like Status.getMessage(exception); because at that position in my code I do not know which exception it was. That why I want to save it inside the status.
Chosen solution
private static class LearnStatus implements Serializable
{
private static final long serialVersionUID = 1L;
public static final LearnStatus OK = new LearnStatus(null);
public static final LearnStatus TIMEOUT = new LearnStatus(null);
public static final LearnStatus NO_TEMPLATE_FOUND = new LearnStatus(null);
public static final LearnStatus QUERY_RESULT_EMPTY = new LearnStatus(null);
public static final LearnStatus NO_QUERY_LEARNED = new LearnStatus(null);
public final Exception exception;
private LearnStatus(Exception exception) {this.exception = exception; }
public static LearnStatus exceptionStatus(Exception cause)
{
if (cause == null) throw new NullPointerException();
return new LearnStatus(cause);
}
@Override public String toString()
{
if(this==OK) {return "OK";}
if(this==TIMEOUT) {return "timeout";}
if(this==NO_TEMPLATE_FOUND) {return "no template found";}
if(this==QUERY_RESULT_EMPTY) {return "query result empty";}
if(this==NO_QUERY_LEARNED) {return "no query learned";}
return "<summary>Exception: <details>"+exception.getLocalizedMessage()+"</details></summary>";
}
}
Problems with that
If I serialize an object with Status.OK in it, after deserialization if(status==Status.OK) does not work anymore.
New solution
I now included an enum type within the class. What do you think about it?
private static class LearnStatus implements Serializable
{
public enum Type {OK, TIMEOUT, NO_TEMPLATE_FOUND,QUERY_RESULT_EMPTY,NO_QUERY_LEARNED,EXCEPTION}
public final Type type;
private static final long serialVersionUID = 1L;
public static final LearnStatus OK = new LearnStatus(Type.OK,null);
public static final LearnStatus TIMEOUT = new LearnStatus(Type.TIMEOUT,null);
public static final LearnStatus NO_TEMPLATE_FOUND = new LearnStatus(Type.NO_TEMPLATE_FOUND,null);
public static final LearnStatus QUERY_RESULT_EMPTY = new LearnStatus(Type.QUERY_RESULT_EMPTY,null);
public static final LearnStatus NO_QUERY_LEARNED = new LearnStatus(Type.NO_QUERY_LEARNED,null);
public final Exception exception;
private LearnStatus(Type type, Exception exception) {this.type=type;this.exception = exception;}
public static LearnStatus exceptionStatus(Exception cause)
{
if (cause == null) throw new NullPointerException();
return new LearnStatus(Type.EXCEPTION,cause);
}
@Override public String toString()
{
switch(type)
{
case OK: return "OK";
case TIMEOUT: return "timeout";
case NO_TEMPLATE_FOUND: return "no template found";
case QUERY_RESULT_EMPTY:return "query result empty";
case NO_QUERY_LEARNED: return "no query learned";
case EXCEPTION: return "<summary>Exception: <details>"+exception.getLocalizedMessage()+"</details></summary>";
default: throw new RuntimeException("switch type not handled");
}
}
}
There are several approaches to this, but all of them depend that you don’t use Enums or that you don’t use them exclusively. Keep in mind that an enum is basically a class that only has well-defined singletons as value.
One possible refactoring of this is to use a normal class with well-defined singletons instead of enums:
You can now check for
status == Status.OKandstatus == Status.TIMEOUT. If your status variable is neither OK nor TIMEOUT, it must be caused by an exception, which you can retrieve viagetException.As a downside, you lose the
switchfunctionality and must check viaif.