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");
}
}
}
I would use an Exception unless everything is OK.
Like
System.out.println("Everything OK!");
} catch(TimeoutException te) {
System.out.println("Timeout :-(")
} catch(Exception e) {
System.out.println("We have an exception: " + e);
}
I don't see any need to use an enum when Exceptions are designed to do this sort of thing.
Adding yet another layer on top of the layer between you and the original exception you can do this.
interface Status {
String getMessage();
}
enum Statuses implements Status {
OK("Everything OK"), TIMEOUT("Timeout :-(");
private final String message;
private Statuses(String message) { this.message = message; }
String getMessage() { return message; }
}
class ExceptionStatus implement Status {
private final String message;
String getMessage() { return "Exception: " + message; }
}
// to print the message
System.out.println(status.getMessage());
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:
class Status implements Serializable {
// for serialization
private enum InternalStatus {
OK, TIMEOUT, EXCEPTION
}
public static final Status OK = new Status(null, InternalStatus.OK);
public static final Status TIMEOUT = new Status(null, InternalStatus.TIMEOUT);
private final Exception exception;
private final InternalStatus internalStatus;
private Status(Exception exception, InternalStatus internalStatus) {
this.exception = exception;
this.internalStatus = internalStatus;
}
public Exception getException() {
return exception;
}
public static Status exceptionStatus(Exception cause) {
if (cause == null) throw new NullPointerException();
return new Status(cause, InternalStatus.EXCEPTION);
}
// deserialization logic handling OK and TIMEOUT being singletons
private final Object readResolve() {
switch (internalStatus) {
case InternalStatus.OK:
return OK;
case InternalStatus.TIMEOUT:
return TIMEOUT;
default:
return this;
}
}
}
You can now check for status == Status.OK and status == Status.TIMEOUT. If your status variable is neither OK nor TIMEOUT, it must be caused by an exception, which you can retrieve via getException.
As a downside, you lose the switch functionality and must check via if.
Related
I have problem with understanding how Java wildcard works in one particular case. Let's say I have class which represents generic response
public class MyResponse<T> {
private final int httpCode;
private final String message;
private final T data;
}
and resolver for that:
public class ResponseResolver {
public void resolve(Either<AppError, MyResponse<?>> responseToResolve) {
//some logic
}
public void resolveOption(Option<MyResponse<?>> responseToResolve) {
//some logic
}
}
and service where response is resolved with resolver
public class FooService {
private final ResponseResolver responseResolver;
public FooService(ResponseResolver responseResolver) {
this.responseResolver = responseResolver;
}
public void resolveFoo() {
Either<AppError, MyResponse<Foo>> either = Option.of(new MyResponse<>(200, "message", new Foo())).toEither(AppError.ERROR);
responseResolver.resolve(either);
}
public void resolveOptionFoo() {
MyResponse<Foo> foo = new MyResponse<>(200, "message", new Foo());
responseResolver.resolveOption(Option.of(foo));
}
}
I do not understand why resolveOption method which is called in resolveFooOption is a proper way but in method with Either compiler complies that required type is Either<AppError, MyResponse<?> but provided Either<AppError, MyResponse<Foo>. Can anybody explain me why second case is invalid?
As of Java 9, methods in an interface can be private. A private method
can be static or an instance method. Since private methods can only be
used in the methods of the interface itself, their use is limited to
being helper methods for the other methods of the interface.
Cay S. Horstmann, Core Java Volume I - Fundamentals
I get that we can put the common functionality in the private methods and not make it accessible to public. But we can have two kind of private methods here:
private
private static
Using private static methods is understandable, but when should we use private methods? We are not dealing with instances here as this is an interface, so why creating private methods is allowed? Don't we need only private static methods?
Interfaces are used to define an object's behaviour. This means all of the interface's methods are exposed. When using default methods, we can provide standard implementations of the defined methods, offering code reuse across class boundaries.
In some cases, functionality is required (perhaps just for code reuse in different default methods) but should not be exposed because it would pollute class'/object's namespaces. This is where private default methods come in handy. Examples private default methods could be factories, validations or default state handling.
package com.company;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Main {
public static void main(final String[] args) {
var messages =
List.of(
MessageQueue.newSubject("Message 1"),
MessageQueue.newTopic("Message 2"),
MessageQueue.newTopic("Message 3"));
final MessageQueueAdapter1 queue1 = () -> messages;
inspectQueue(queue1);
final MessageQueueAdapter2 queue2 = () -> messages;
inspectQueue(queue2);
}
private static void inspectQueue(final MessageQueue queue) {
final List<Message> messagesWithSubject = queue.getMessagesWithSubject();
assert messagesWithSubject.size() == 1 : "expected one message with 'Subject'";
final List<Message> messagesWithTopic = queue.getMessagesWithTopic();
assert messagesWithTopic.size() == 2 : "expected two message with 'Topic'";
assert !queue.getMessages().isEmpty() && 3 == queue.getMessages().size()
: "expected three messages in total";
}
#FunctionalInterface
interface Message {
private static boolean isPrefixedBy(final String message, final String prefix) {
return message != null && !message.isEmpty() && message.startsWith(prefix);
}
default boolean hasSubject() {
return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_SUBJECT);
}
default boolean hasTopic() {
return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_TOPIC);
}
String getMessage();
}
interface MessageQueue {
String PREFIX_SUBJECT = "Subject: ";
String PREFIX_TOPIC = "Topic: ";
private static Message newMessage(final String message) {
return () -> message;
}
static Message newSubject(final String message) {
return newMessage(PREFIX_SUBJECT + message);
}
static Message newTopic(final String message) {
return newMessage(PREFIX_TOPIC + message);
}
List<Message> getMessages();
List<Message> getMessagesWithSubject();
List<Message> getMessagesWithTopic();
}
#FunctionalInterface
interface MessageQueueAdapter1 extends MessageQueue {
private static List<Message> filterBy(
final List<Message> messages, final Predicate<Message> predicate) {
return messages.stream().filter(predicate).collect(Collectors.toList());
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithSubject() {
return filterBy(this.getMessages(), Message::hasSubject);
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithTopic() {
return filterBy(this.getMessages(), Message::hasTopic);
}
}
#FunctionalInterface
interface MessageQueueAdapter2 extends MessageQueue {
private List<Message> filterBy(final Predicate<Message> predicate) {
return this.getMessages().stream().filter(predicate).collect(Collectors.toList());
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithSubject() {
return filterBy(Message::hasSubject);
}
/** {#inheritDoc} */
#Override
default List<Message> getMessagesWithTopic() {
return filterBy(Message::hasTopic);
}
}
}
OK, another attempt at actually answering OP's questions. When you need to call another non-static method on the interface from a private method, the private method cannot be static. For example, there would be a compilation error if the private method below was static:
public interface InterfaceWithMethods {
public default void doSomething() {
doSomethingCommon();
}
public default void doSomethingElse() {
doSomethingCommon();
}
public void actuallyDoSomething();
private void doSomethingCommon() {
System.out.println("Do something first.");
actuallyDoSomething();
}
}
I have RESTeasy service. And have implemented simple error handling on methods using try catch and feel something is not very well with it. I've noticed try catch repetition on all my methods. So I want ask way how to avoid repetition (to reduce code size) of try catch but not lost functionality.
#Path("/rest")
#Logged
#Produces("application/json")
public class CounterRestService {
#POST
#Path("/create")
public CounterResponce create(#QueryParam("name") String name) {
try {
CounterService.getInstance().put(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#POST
#Path("/insert")
public CounterResponce create(Counter counter) {
try {
CounterService.getInstance().put(counter);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#DELETE
#Path("/delete")
public CounterResponce delete(#QueryParam("name") String name) {
try {
CounterService.getInstance().remove(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
... // other methods with some try catch pattern
response
public class CounterResponce {
private String status;
#JsonSerialize(include=Inclusion.NON_NULL)
private Object data;
public CounterResponce() {
this.status = "ok";
}
public CounterResponce(Object o) {
this.status = "ok";
this.data = o;
}
public CounterResponce(String status, Object o){
this.status = status;
this.data = o;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
exceptions source
public class CounterService {
private Map<String, StatisticCounter> counters = new HashMap<String, StatisticCounter>();
private static CounterService instance = null;
protected CounterService() {}
public static CounterService getInstance() {
if(instance == null) {
instance = new CounterService();
}
return instance;
}
public StatisticCounter get(String name){
StatisticCounter c = counters.get(name);
if(c == null)throw new IllegalArgumentException("Counter "+name+" not exist");
return c;
}
public void put(String name){
if(name==null)throw new IllegalArgumentException("null can`t be as name");
if(counters.get(name)!=null)throw new IllegalArgumentException("Counter "+name+" exist");
counters.put(name, new Counter(name));
}...
The comments in your question are pointing you in a good direction. Since the answers do not mention it, I'll summarize the general idea in this answer.
Extending WebApplicationException
JAX-RS allows to define direct mapping of Java exceptions to HTTP error responses. By extending WebApplicationException, you can create application specific exceptions that build a HTTP response with the status code and an optional message as the body of the response.
The following exception builds a HTTP response with the 404 status code:
public class CustomerNotFoundException extends WebApplicationException {
/**
* Create a HTTP 404 (Not Found) exception.
*/
public CustomerNotFoundException() {
super(Responses.notFound().build());
}
/**
* Create a HTTP 404 (Not Found) exception.
* #param message the String that is the entity of the 404 response.
*/
public CustomerNotFoundException(String message) {
super(Response.status(Responses.NOT_FOUND).
entity(message).type("text/plain").build());
}
}
WebApplicationException is a RuntimeException and doesn't need to the wrapped in a try-catch block or be declared in a throws clause:
#Path("customers/{customerId}")
public Customer findCustomer(#PathParam("customerId") Long customerId) {
Customer customer = customerService.find(customerId);
if (customer == null) {
throw new CustomerNotFoundException("Customer not found with ID " + customerId);
}
return customer;
}
Creating ExceptionMappers
In other cases it may not be appropriate to throw instances of WebApplicationException, or classes that extend WebApplicationException, and instead it may be preferable to map an existing exception to a response.
For such cases it is possible to use a custom exception mapping provider. The provider must implement the ExceptionMapper<E extends Throwable> interface. For example, the following maps the JAP EntityNotFoundException to a HTTP 404 response:
#Provider
public class EntityNotFoundExceptionMapper
implements ExceptionMapper<EntityNotFoundException> {
#Override
public Response toResponse(EntityNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain").build();
}
}
When an EntityNotFoundException is thrown, the toResponse(E) method of the EntityNotFoundExceptionMapper instance will be invoked.
The #Provider annotation declares that the class is of interest to the JAX-RS runtime. Such class may be added to the set of classes of the Application instance that is configured.
Introduce a private method such as "apply" which can take function as parameter if you use Java 8. This method will have the error handling and/or mapping, response mapping and response generation code centralized.
From create and delete methods, invoke this apply method and pass the desired counter operation you wish to perform as a lambda expression.
I am trying to pull data from class in another class and populate a JPanel with the data, but it is not working for some reason.
Here is the full restConnector class where I pull the JSON data.
As far as I know this works fine.
public class restConnector {
private static final Logger LOGGER = LoggerFactory.getLogger(restConnector.class);
private static final restConnector INSTANCE = new restConnector();
public static restConnector getInstance() {
return restConnector.INSTANCE;
}
private restConnector(){
}
private static String user = "ss";
private static String pwd = "ee
public static String encode(String user, String pwd) {
final String credentials = user+":"+pwd;
BASE64Encoder encoder = new sun.misc.BASE64Encoder();
return encoder.encode(credentials.getBytes());
}
//Open REST connection
public static void init() {
restConnector.LOGGER.info("Starting REST connection...");
try {
Client client = Client.create();
client.addFilter(new LoggingFilter(System.out));
WebResource webResource = client.resource("https://somewebpage.com/
String url = "activepersonal";
ClientResponse response = webResource
.path("api/alerts/")
.queryParam("filter", ""+url)
.header("Authorization", "Basic "+encode(user, pwd))
.header("x-api-version", "1")
.accept("Application/json")
.get(ClientResponse.class);
if (response.getStatus() != 200) {
}else{
restConnector.LOGGER.info("REST connection STARTED.");
}
String output = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyNameStrategy());
try {
List<Alert> alert = mapper.readValue(output, new TypeReference<List<Alert>>(){});
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
}
}
However, when I try to pull the data in another class it gives me just null values from the system.out.print inside refreshData() method. Here is the code that is supposed to print the data
public class Application{
Alert alerts = new Alert();
public Application() {
refreshData();
}
private void initComponents() {
restConnector.init();
refreshData();
}
private void refreshData() {
System.out.println("appalertList: "+alerts.getComponentAt(0));
}
}
Here is my Alert class
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(Include.NON_EMPTY)
public class Alert {
private int pasID;
private String status;
private boolean shared;
private String header;
private String desc;
public int getPasID() {
return pasID;
}
public void setPasID(int pasID) {
this.pasID = pasID;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public boolean isShared() {
return shared;
}
public void setShared(boolean shared) {
this.shared = shared;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\n***** Alert Details *****\n");
sb.append("PasID="+getPasID()+"\n");
sb.append("Status="+getStatus()+"\n");
sb.append("Shared="+isShared()+"\n");
sb.append("Header="+getHeader()+"\n");
sb.append("Description="+getDesc()+"\n");
sb.append("*****************************");
return sb.toString();
}
public String getComponentAt(int i) {
return toString();
}
}
I'm kind a lost with this and been stuck here for a couple of days already so all help would be really appreciated. Thanks for the help in advance.
Edit: Formatted the code a bit and removed the NullPointerException as it was not happening anymore.
As stated in comments:
Me: In your first bit of code you have this try { List<Alert> alert.., but you do absolutely nothing with the newly declared alert List<Alert>. It this where the data is supposed to be coming from?
OP: I'm under the impression that that bit of code is the one that pushes the JSON Array to the Alert.class. Is there something I'm missing there?
Me: And what makes you think it does that? All it does is read the json, and the Alert.class argument is the class type argument, so the mapper know the results should be mapped to the Alert attributes when it creates the Alert objects. That's how doing List<Alert> is possible, because passing Alert.class decribes T in List<T>. The List<Alert> is what's returned from the reading, but you have to determine what to actually do with the list. And currently, you do absolutely nothing with it
You maybe want to change the class just a bit.
Now this is in no way a good design, just an example of how you can get it to work. I would take some time to sit and think about how you want the restConnector to be fully utilized
That being said, you can have a List<Alert> alerts; class member in the restConnector class. And have a getter for it
public class restConnector {
private List<Alert> alerts;
public List<Alert> getAlerts() {
return alerts;
}
...
}
Then when deserializing with the mapper, assign the value to private List<Alert> alerts. What you are doing is declaring a new locally scoped list. So instead of
try {
List<Alert> alert = mapper.readValue...
do this instead
try {
alerts = mapper.readValue
Now the class member is assigned a value. So in the Application class you can do something like
public class Application {
List<Alert> alerts;
restConnector connect;
public Application() {
initComponents();
}
private void initComponents() {
connector = restConnector.getInstance();
connector.init();
alerts = connector.getAlerts();
refreshData();
}
private void refreshData() {
StringBuilder sb = new StringBuilder();
for (Alert alert : alerts) {
sb.append(alert.toString()).append("\n");
}
System.out.println("appalertList: "+ sb.toString());
}
}
Now you have access to the Alerts in the list.
But let me reiterate: THIS IS A HORRIBLE DESIGN. For one you are limiting the init method to one single call, in which it is only able to obtain one and only one resource. What if the rest service needs to access a different resource? You have made the request set in stone, so you cant.
Take some time to think of some good OOP designs where the class can be used for different scenarios.
I have an ExecutorService that is used to handle a stream of tasks. The tasks are represented by my DaemonTask class, and each task builds a response object which is passed to a response call (outside the scope of this question). I am using a switch statement to spawn the appropriate task based on a task id int. It looks something like;
//in my api listening thread
executorService.submit(DaemonTask.buildTask(int taskID));
//daemon task class
public abstract class DaemonTask implements Runnable {
public static DaemonTask buildTask(int taskID) {
switch(taskID) {
case TASK_A_ID: return new WiggleTask();
case TASK_B_ID: return new WobbleTask();
// ...very long list ...
case TASK_ZZZ_ID: return new WaggleTask();
}
}
public void run() {
respond(execute());
}
public abstract Response execute();
}
All of my task classes (such as WiggleTask() ) extend DaemonTask and provide an implementation for the execute() method.
My question is simply; is this pattern reasonable? Something feels wrong when I look at my huge switch case with all its return statements. I have tried to come up with a more elegant lookup table solution using reflection in some way but can't seem to figure out an approach that would work.
Do you really need so many classes? You could have one method per taskId.
final ResponseHandler handler = ... // has many methods.
// use a map or array or enum to translate transIds into method names.
final Method method = handler.getClass().getMethod(taskArray[taskID]);
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
method.invoke(handler);
}
});
If you have to have many classes, you can do
// use a map or array or enum to translate transIds into methods.
final Runnable runs = Class.forName(taskClassArray[taskID]).newInstance();
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
runs.run();
}
});
You can use an enum:
public enum TaskBuilder
{
// Task definitions
TASK_A_ID(1){
#Override
public DaemonTask newTask()
{
return new WiggleTask();
}
},
// etc
// Build lookup map
private static final Map<Integer, TaskBuilder> LOOKUP_MAP
= new HashMap<Integer, TaskBuilder>();
static {
for (final TaskBuilder builder: values())
LOOKUP_MAP.put(builder.taskID, builder);
}
private final int taskID;
public abstract DaemonTask newTask();
TaskBuilder(final int taskID)
{
this.taskID = taskID;
}
// Note: null needs to be handled somewhat
public static TaskBuilder fromTaskID(final int taskID)
{
return LOOKUP_MAP.get(taskID);
}
}
With such an enum, you can then do:
TaskBuilder.fromTaskID(taskID).newTask();
Another possibility is to use a constructor field instead of a method, that is, you use reflection. It is much easier to write and it works OK, but exception handling then becomes nothing short of a nightmare:
private enum TaskBuilder
{
TASK_ID_A(1, WiggleTask.class),
// others
// Build lookup map
private static final Map<Integer, TaskBuilder> LOOKUP_MAP
= new HashMap<Integer, TaskBuilder>();
static {
for (final TaskBuilder builder: values())
LOOKUP_MAP.put(builder.taskID, builder);
}
private final int index;
private final Constructor<? extends DaemonTask> constructor;
TaskBuilder(final int index, final Class<? extends DaemonTask> c)
{
this.index = index;
// This can fail...
try {
constructor = c.getConstructor();
} catch (NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
// Ewww, three exceptions :(
public DaemonTask newTask()
throws IllegalAccessException, InvocationTargetException,
InstantiationException
{
return constructor.newInstance();
}
// Note: null needs to be handled somewhat
public static TaskBuilder fromTaskID(final int taskID)
{
return LOOKUP_MAP.get(taskID);
}
}
This enum can be used the same way as the other one.